spacedriveapp / spacedriveapp/spacebot

Container runs as root with silent sandbox passthrough on backend failure

Open
#405 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
2.4k
Forks
367
PR merge metrics
No merged PRs in 30d

Description

The Dockerfile has no USER instruction, so the daemon runs as root inside the container. Combined with a silent degradation path in the sandbox backend detection, this creates a privilege escalation risk under realistic deployment conditions.

The sandbox degradation path:

SandboxMode (the config value) and SandboxBackend (what's actually available at runtime) are independent. When mode is Enabled but no working backend is detected, wrap() falls through to wrap_passthrough() at sandbox.rs:466 — which runs the subprocess with no filesystem isolation. The only signal is a tracing::warn at sandbox.rs:219. Nothing in the health check, API status, or startup output surfaces this to an operator as a hard failure.

When this happens in Docker:

The Dockerfile installs bubblewrap, so under normal conditions the sandbox works. The risk has two distinct failure modes:

  1. bwrap absent from PATH (removed, different base image, stripped by policy): detect_bubblewrap() at sandbox.rs:930 returns SandboxBackend::None, wrap() silently falls through to wrap_passthrough(), and shell commands run as root with no OS-level containment. This is the silent-degradation path.
  2. bwrap present but non-functional (CAP_SYS_ADMIN dropped, user namespaces disabled by container runtime): detect_bubblewrap() runs a real probe (bwrap --ro-bind / / --proc /proc -- /usr/bin/true) at sandbox.rs:939-953, but on failure it returns SandboxBackend::Bubblewrap { proc_supported: false } rather than None. Subsequent wrap_bubblewrap() invocations fail at spawn time (shell.rs:251), surfacing as tool errors to the LLM. This fails closed — no silent passthrough — but every shell command is broken with no clear startup diagnostic.

In both cases the container is running as root, so any containment gap (mode 1) or future bwrap CVE gives full root access.

Potential Fixes:
  1. Add RUN useradd -ms /bin/bash spacebot and USER spacebot before ENTRYPOINT in the Dockerfile. This is the most impactful single change — it limits blast radius regardless of sandbox state.
  2. In sandbox.rs, treat SandboxBackend::None with SandboxMode::Enabled as a fatal startup error (or a non-OK health check response), not a warn-and-continue. Operators deploying in Docker expect containment to be active.
  3. detect_bubblewrap() already runs a real probe (bwrap --ro-bind / / --proc /proc -- /usr/bin/true), but on failure it still returns Bubblewrap { proc_supported: false }. It should return SandboxBackend::None when the probe fails entirely, not just demote the proc_supported flag. A backend that can't create namespaces should not be reported as available.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read the Dockerfile and the referenced paths in sandbox.rs and shell.rs, starting with wrap(), detect_bubblewrap(), and the spawn failure handling. Trace how unavailable or non-functional backends are reported through startup, health, and API status. Done means the container is non-root and enabled sandboxing cannot silently fall back to an uncontained subprocess.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, rust
Domain
devops, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.