You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Claude Code sandbox (bwrap) cannot start in workers: /proc/sys is read-only #528
Claude review lanes on ci-runner workers cannot start the Claude Code sandbox. Every Bash call fails with:
bwrap: cannot open /proc/sys/user/max_user_namespaces: Read-only file system
Reported in melodic-software/ci-workflows#938 (lane comments on melodic-software/dotfiles#1383-#1394 since 2026-10-30, and melodic-software/provisioning#882's security lane). As a workaround, ci-workflows pinned claude-code-action at v1.0.253 (melodic-software/ci-workflows#939), held by an ignore at .github/dependabot.yml:34 there. The pin and the ignore can go once this is fixed.
Docker mounts /proc/sys read-only in every container. The userns seccomp profile (README "seccompProfile") allows unprivileged user namespaces, but no worker setting changes /proc/sys's mount, and README.md:366-367 says none can add privileges.
Cause: UNVERIFIED. It looks like the bwrap that newer claude-code-action releases run writes /proc/sys/user/max_user_namespaces (for example to disable nested user namespaces), and that write needs /proc/sys writable.
Expected
The Claude Code sandbox starts in a worker on a target with seccompProfile: userns, without privileged mode, the Docker socket, or added capabilities.
Fix
Confirm which bwrap invocation opens the file and why. Then pick the narrowest change:
a worker setting that leaves /proc/sys writable only inside the job's own user namespace;
a sandbox option on the caller side that skips the write;
a change upstream.
Any option that widens the worker boundary is an owner decision.
The failing write is bubblewrap's --disable-userns. It opens sys/user/max_user_namespaces with O_WRONLY and dies with exactly our message when the open fails (bubblewrap.c:3395-3405). Docker's default ReadonlyPaths includes /proc/sys (moby defaults.go:110-116), so the open fails in every worker.
sandbox-runtime passes --disable-userns only when no apply-seccomp helper is in use (linux-sandbox-utils.ts:3847-3860). That code's own comment says bubblewrap "dies on the read-only /proc/sys of an unprivileged container". The behaviour came from sandbox-runtime#588.
First failing release: claude-code-action v1.0.254 (Claude Code 2.1.304). The --disable-userns string occurs 0 times in the 2.1.303 binary and 3 times in the 2.1.304 binary.
Why no helper: a native Claude Code build finds apply-seccomp only in its own bundled vendor paths or in a global npm install of @anthropic-ai/sandbox-runtime (vendor/seccomp/<arch>/apply-seccomp) (generate-seccomp-filter.ts:194-330). When it finds neither, it logs "apply-seccomp binary not available - unix socket blocking disabled. Install @anthropic-ai/sandbox-runtime globally for full protection." (linux-sandbox-utils.ts:3624-3629).
Fix
Install @anthropic-ai/sandbox-runtime globally, at a pinned version, in the lane workflow, next to the existing bubblewrap and socat install (melodic-software/ci-workflows pr-review.yml, around line 815). Claude Code's sandboxing docs give the same instruction.
With the helper in the chain, bubblewrap gets no --disable-userns.
The helper's own write to max_user_namespaces is non-fatal. Its seccomp filter then blocks nested user namespaces and AF_UNIX sockets (apply-seccomp.c:885-896).
So the sandbox gains protection and the worker boundary does not change.
One install covers both the self-hosted and the GitHub-hosted lanes.
Rejected:
sandbox.allowNestedUserNamespaces: ignored under CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1 (settings reference).
enableWeakerNestedSandbox: bind-mounts the container's /proc into the sandbox, which works against the scrub's PID isolation.
Docker ReadonlyPaths overrides or systempaths=unconfined: these widen the worker boundary.
UNVERIFIED until a worker lane run proves it:
that the helper's nested unshare passes the userns seccomp profile;
that a sandbox-runtime version pinned apart from Claude Code's bundled one works with that Claude Code.
No ci-runner code change is expected. This issue stays open until a self-hosted lane on the latest claude-code-action runs Bash successfully.
Both runs log installed apply-seccomp from sandbox-runtime 0.0.81 at /usr/local/lib/node_modules/@anthropic-ai/sandbox-runtime/vendor/seccomp/x64/apply-seccomp.
cannot open /proc/sys/user/max_user_namespaces occurs 0 times in either log.
With the helper in the chain, sandbox-runtime passes no --disable-userns, so bubblewrap never writes the read-only /proc/sys (cause and source lines in the comment above).
Reopening. The evidence I closed this on does not show that Bash runs inside the review session.
The check I used can't see the failure. "cannot open /proc/sys/user/max_user_namespaces occurs 0 times" was read from the job logs. The logs do not include Claude's tool results, so a Bash failure inside the review never shows up there.
Both review lanes on melodic-software/provisioning#952 report a failing shell. They ran on ci-runner-melo-desk-001 at head cdebbe7 (run 42499720828), with claude-code-action 61a9c274 (v1.0.269) and installed apply-seccomp from sandbox-runtime 0.0.81.
claude-review: "The Bash tool failed in this session (the sandbox could not start), so I ran no commands."
claude-security-review: "The sandbox's Bash tool failed (bwrap, read-only /proc)."
The workflow's own probe passes and doesn't test this path. The probe runs only bwrap --unshare-pid --dev-bind / / true, and it passed ("bwrap created a PID namespace; the subprocess sandbox can start"). The helper's path is never exercised.
A likely second cause, UNVERIFIED. In sandbox-runtime, the apply-seccomp nested-userns path writes /proc/self/setgroups and uid_map. Without a fresh --proc, --ro-bind / / leaves /proc read-only and those writes fail with EROFS (linux-sandbox-utils.ts:3835-3838).
Next step: capture the review session's actual Bash tool error, either from the execution file or from a run with SRT_DEBUG=1 that prints tool results.
Third data point: the claude-review on melodic-software/provisioning#952 at head b33ba5d (after the v1.0.269 pin and the apply-seccomp helper install) also says "Bash was unavailable in this sandbox, so I did not run the Pester tests or ci-runner config validate." The fault persists on current ci-workflows.
https://github.com/melodic-software/provisioning/actions/runs/42516497284 (code review): 'claude-review: tool=Read target=/home/runner/_work/provisioning/provisioning/.claude-lane/pr.diff error=false' and Bash calls ok (64, 59 and 30 lines). Its two error=true calls are permission prompts, not sandbox errors.
Activity
kyle-sexton commentedon Nov 8, 2026
Cause (confirmed from source)
--disable-userns. It openssys/user/max_user_namespaceswithO_WRONLYand dies with exactly our message when the open fails (bubblewrap.c:3395-3405). Docker's defaultReadonlyPathsincludes/proc/sys(moby defaults.go:110-116), so the open fails in every worker.--disable-usernsonly when noapply-seccomphelper is in use (linux-sandbox-utils.ts:3847-3860). That code's own comment says bubblewrap "dies on the read-only /proc/sys of an unprivileged container". The behaviour came from sandbox-runtime#588.--disable-usernsstring occurs 0 times in the 2.1.303 binary and 3 times in the 2.1.304 binary.apply-seccomponly in its own bundled vendor paths or in a global npm install of@anthropic-ai/sandbox-runtime(vendor/seccomp/<arch>/apply-seccomp) (generate-seccomp-filter.ts:194-330). When it finds neither, it logs "apply-seccomp binary not available - unix socket blocking disabled. Install @anthropic-ai/sandbox-runtime globally for full protection." (linux-sandbox-utils.ts:3624-3629).Fix
Install
@anthropic-ai/sandbox-runtimeglobally, at a pinned version, in the lane workflow, next to the existing bubblewrap and socat install (melodic-software/ci-workflowspr-review.yml, around line 815). Claude Code's sandboxing docs give the same instruction.--disable-userns.max_user_namespacesis non-fatal. Its seccomp filter then blocks nested user namespaces and AF_UNIX sockets (apply-seccomp.c:885-896).Rejected:
sandbox.allowNestedUserNamespaces: ignored underCLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1(settings reference).enableWeakerNestedSandbox: bind-mounts the container's/procinto the sandbox, which works against the scrub's PID isolation.ReadonlyPathsoverrides orsystempaths=unconfined: these widen the worker boundary.UNVERIFIED until a worker lane run proves it:
usernsseccomp profile;No ci-runner code change is expected. This issue stays open until a self-hosted lane on the latest claude-code-action runs Bash successfully.
feat(image): ship bubblewrap and socat so review jobs skip apt (#533)
kyle-sexton commentedon Nov 8, 2026
Fixed in melodic-software/ci-workflows with no ci-runner change:
apply-seccomphelper, a best-effort install checked against its SHA-256.61a9c274, "bump Claude Code to 2.1.319".Evidence from review lanes on ci-runner workers on the latest action, both successful:
ci-runner-melo-desk-001, and provisioning run 42499720854, onci-runner-melo-lap-001.installed apply-seccomp from sandbox-runtime 0.0.81 at /usr/local/lib/node_modules/@anthropic-ai/sandbox-runtime/vendor/seccomp/x64/apply-seccomp.cannot open /proc/sys/user/max_user_namespacesoccurs 0 times in either log.With the helper in the chain, sandbox-runtime passes no
--disable-userns, so bubblewrap never writes the read-only/proc/sys(cause and source lines in the comment above).kyle-sexton commentedon Nov 8, 2026
Reopening. The evidence I closed this on does not show that Bash runs inside the review session.
cannot open /proc/sys/user/max_user_namespacesoccurs 0 times" was read from the job logs. The logs do not include Claude's tool results, so a Bash failure inside the review never shows up there.ci-runner-melo-desk-001at headcdebbe7(run 42499720828), with claude-code-action61a9c274(v1.0.269) andinstalled apply-seccomp from sandbox-runtime 0.0.81./proc)."bwrap --unshare-pid --dev-bind / / true, and it passed ("bwrap created a PID namespace; the subprocess sandbox can start"). The helper's path is never exercised./proc/self/setgroupsanduid_map. Without a fresh--proc,--ro-bind / /leaves/procread-only and those writes fail with EROFS (linux-sandbox-utils.ts:3835-3838).Next step: capture the review session's actual Bash tool error, either from the execution file or from a run with
SRT_DEBUG=1that prints tool results.kyle-sexton commentedon Nov 8, 2026
Third data point: the claude-review on melodic-software/provisioning#952 at head b33ba5d (after the v1.0.269 pin and the apply-seccomp helper install) also says "Bash was unavailable in this sandbox, so I did not run the Pester tests or
ci-runner config validate." The fault persists on current ci-workflows.fix(seccomp): allow unshare of PID and mount namespaces in a job user…
kyle-sexton commentedon Nov 8, 2026
Verified fixed on v0.1.38 workers with ci-workflows #1054 (full sandbox) and #539 (seccomp rule). Tool-call lines from ci-workflows #1056:
Closing. ci-workflows#938 is closed with the same evidence.