12. Treat the read-write workspace as untrusted: default to $PWD, source config from /etc#
Date: 2026-05-29
Status#
Accepted
Context#
The workspace is bound rw into the sandbox, so a compromised session can write
to it. Two facets followed from taking that seriously. (1) The early bind
exposed all of /workspaces — every sibling project — rw. (2) Sandbox config
(workspace-root, allow-write, …) was first read from
$PWD/.devcontainer/claude-sandbox.conf, inside the rw workspace.
Decision#
Treat the rw workspace as attacker-writable input, on two fronts:
Default the workspace bind to
$PWD— only the current project is writable (PR #29, issue #28). Restoring the broad/workspacesbind is an explicit opt-in (CLAUDE_SANDBOX_WORKSPACE_ROOT=/workspaces).Read sandbox config from host-global
/etc/claude-sandbox.conf, never from the workspace (PR #32, commitf6fcc3d)./etcis not in the rw bind set. A per-workspace conf is attacker-writable from inside the jail: a compromised session could writeallow-write = /(orworkspace-root = /) and the next launch would--bindit rw — a cross-session breakout.
Consequences#
One global conf applies to every workspace with nothing added per repo; edit the clone conf and re-run
./install(a rebuild does it viapostCreate) to change it. Per-sessionCLAUDE_SANDBOX_*env vars remain the supported per-session override.verify-sandboxcheck 18 guards that the installed shadow reads/etcand has no$PWD/.devcontainerread.Refuse “make
allow-writeper-repo again so projects can opt in” — it reopens the bind-escalation vector. The same “security-relevant inputs live outside the rw set” discipline governs where the integrity guard lives (13. Deliver the integrity guard globally via managed-settings). A residual re-stamp vector (the global conf is itself re-placed from the clone on rebuild) is tracked in issue #35.