[BUG] 2.1.216 sandbox regression: default `--cap-drop ALL` breaks all Bash on root installs (apply-seccomp: write /proc/self/uid_map: Operation not permitted)
Preflight Checklist
- [x] I have searched existing issues. The closest are #43454, #48304, #73786, #44180 — this is a distinct regression (root install,
uid_mapwrite, introduced by 2.1.216's new--cap-drop ALLdefault); see "Relation to existing issues" below. - [x] This is a single bug report.
- [x] I am using the latest version of Claude Code.
What's Wrong?
Starting with 2.1.216, on a Claude Code install that runs as root on Linux/WSL2 (kernel ≥ 5.12), every sandboxed Bash tool call dies before the user command runs:
apply-seccomp: write /proc/self/uid_map: Operation not permitted
2.1.215 worked fine. 2.1.216 auto-updated overnight and broke all Bash. dangerouslyDisableSandbox: true does not help (the sandboxed pre-flight dies first).
Root cause (from inspecting the bundled binaries): 2.1.216 added --unshare-user --cap-drop ALL to the default bwrap sandbox args (the non-weaker branch). In 2.1.215 that branch was just --dev /dev --unshare-pid --proc /proc — no user namespace, no capability drop.
Independently verifiable regression marker (no decompiler needed — the string is entirely new in 2.1.216):
$ for v in 2.1.212 2.1.215 2.1.216; do
printf '%s: ' "$v"
strings -a ~/.local/share/claude/versions/$v | grep -c -- '--cap-drop'
done
2.1.212: 0
2.1.215: 0
2.1.216: 2
Why it only breaks root installs: the sandbox re-execs the bundled apply-seccomp helper, which creates a nested user namespace and writes 0 0 1 to /proc/self/uid_map. Since Linux 5.12, the kernel's verify_root_map check requires CAP_SETFCAP to map uid 0. But the preceding --cap-drop ALL empties the bounding set, so the euid-0 process re-execed inside the userns holds zero capabilities (CapBnd/CapEff = 0000000000000000) → the uid-0 map write returns EPERM. A non-root install maps e.g. 1000 1000 1 (lower id ≠ 0), so verify_root_map never fires — which is exactly why this is root-specific, and why the closely-related #43454 / #48304 (non-root, failing at the earlier setgroups write) are a different manifestation of the same nested-userns fragility rather than the same bug.
What Should Happen?
Sandboxed Bash should run on root installs, as it did in 2.1.215.
Confirmed fix
Adding --cap-add CAP_SETFCAP to the bwrap invocation (retaining just that one capability through the drop) makes the uid-0 map succeed and Bash works again — verified by replaying 2.1.216's exact wrapper args with --cap-add CAP_SETFCAP added. Alternatively, skip the nested uid_map write (or use an identity map) when geteuid() == 0.
Error Messages/Logs
apply-seccomp: write /proc/self/uid_map: Operation not permitted
Steps to Reproduce
- Run Claude Code as root on Linux or WSL2 (kernel ≥ 5.12).
- Native Bash sandbox enabled (
sandbox.enabled: true). - On ≥ 2.1.216, every Bash tool call fails with the error above. On ≤ 2.1.215 it works. The only delta is the new
--unshare-user --cap-drop ALLdefault args (see thestringsmarker above).
Workarounds (for other root users hitting this)
sandbox.network.allowAllUnixSockets: truein settings — skips theapply-seccompseccomp step entirely while keeping the rest of the 2.1.216 sandbox (filesystem binds,--unshare-net,--cap-drop ALL). Confirmed working. (Related feature: #44180.)sandbox.enableWeakerNestedSandbox: trueavoids--cap-drop ALL, but is silently forced tofalsewhenCLAUDE_CODE_SUBPROCESS_ENV_SCRUBis set (#73786), so it is not a reliable workaround.- Pin/downgrade to 2.1.215 — but the auto-updater re-bumps to ≥ 2.1.216 on next launch.
Relation to existing issues
- #43454 / #48304 — same
apply-seccompnested-userns capability restriction, but those fail at the earlier/proc/self/setgroupswrite on non-root installs and predate the--cap-drop ALLdefault. This report is the root +uid_map+ 2.1.216--cap-drop ALLvariant. - #73786 — the
CLAUDE_CODE_SUBPROCESS_ENV_SCRUBinteraction that makesenableWeakerNestedSandboxa non-workaround here. - #44180 — the
allowAllUnixSocketsknob used as the working workaround.
Claude Model
Opus
Is this a regression?
Yes.
Last Working Version
2.1.215
Claude Code Version
2.1.216
Platform
Claude subscription (Max)
Operating System
WSL2 (Ubuntu) on Windows, kernel 6.6.114.1-microsoft-standard-WSL2, Claude Code running as root.
3 Comments
Sibling regression from the same 2.1.216 sandbox hardening wave, but a different code path / failure / fix — filed separately as #79997.
That one is a non-root install whose workspace/HOME sits under a root-owned directory (
/opt/...): the sandbox's ancestor-walk denyWrite mountpoints can't be created, so bwrap aborts withbwrap: Can't mkdir /opt/.claude: Permission deniedbefore any command runs. Same "2.1.215 fine, 2.1.216 breaks all Bash,dangerouslyDisableSandboxdoesn't help" shape as here, but the fix is orthogonal to--cap-add CAP_SETFCAP(it's about write-deny mountpoint creation being fail-closed instead of fail-open). Cross-linking for triage.Reproduced, and confirmed as a regression at exactly the version you identified.
On the latest release (2.1.233), running as root on Linux with the Bash sandbox enabled (bubblewrap and socat installed), every sandboxed Bash tool call fails before the command runs with exactly:
A/B testing in the identical environment: 2.1.215 runs sandboxed Bash successfully as root; 2.1.216 fails with the error above, as does 2.1.233 — so the regression was introduced in 2.1.216 and is still present. We also verified your version marker independently against the published binaries: the new capability-drop arguments first appear in 2.1.216 and are absent in 2.1.215, exactly as you found.
Your analysis of why this only affects root installs (the uid-0 mapping in the nested user namespace requiring a capability that the new default drops, on kernels ≥ 5.12) is consistent with everything we observed, and thank you for isolating it from the related non-root reports — this is indeed a distinct manifestation.
Marking as a reproduced regression since 2.1.216. Until a fix ships, the workaround you confirmed (
sandbox.network.allowAllUnixSockets: true) is the most reliable option for root installs.🤖 Generated with Claude Code
For your information: the label
reproducedon this issue does not prevent it from becoming stale and eventually auto-closed. See https://github.com/anthropics/claude-code/issues/87647 for details, and consider upvoting that for visibility.