WSL2: sandbox init fails on hardcoded bind of /mnt/c/Program Files/ClaudeCode; silently downgrades to unsandboxed execution
Environment
- Claude Code version: 2.1.223 (npm global install, native ELF binary)
- Platform: Windows 11 host + WSL2 Ubuntu-24.04 (running Claude Code inside WSL)
- Sandbox:
sandbox.enabled: true(bubblewrap/bwrap backend) - Standalone comparison:
@anthropic-ai/sandbox-runtime0.0.70 (srt trueworks fine) - Date found: 2026-08-06
Summary
When sandbox.enabled=true under WSL2, Claude Code's bwrap sandbox setup unconditionally bind-mounts the hardcoded WSL managed-settings path /mnt/c/Program Files/ClaudeCode (constant C8 in the binary; used for reading the Windows enterprise managed-settings.json from inside WSL). If C:\Program Files\ClaudeCode does not exist on the Windows side, bwrap tries to create the mount point and fails, so the sandbox never initializes:
bwrap: Can't mkdir /mnt/c/Program Files/ClaudeCode: Permission denied
(A non-root WSL user cannot mkdir under /mnt/c/Program Files on drvfs, so the mount-point creation is guaranteed to fail on any machine without that directory.)
Security-relevant part: with allowUnsandboxedCommands: true, this hard failure is silently downgraded to unsandboxed execution — the UI just shows "Retrying without the sandbox". Every command the user believes is sandboxed actually runs unsandboxed, on every invocation, with no prominent warning. A user who enabled the sandbox on purpose has no signal that it is permanently non-functional.
Standalone srt true (sandbox-runtime 0.0.70) works on the same machine because it does not bind that path — the regression is specific to Claude Code's extra managed-settings bind.
Steps to reproduce
- Windows 11 host without
C:\Program Files\ClaudeCode(i.e., no enterprise managed settings installed — the default for individual users). - WSL2 Ubuntu-24.04, Claude Code 2.1.223 installed via npm as a global package (native ELF binary), running as a normal non-root user.
- Enable the sandbox in settings:
"sandbox": { "enabled": true }. - Run any Bash command through Claude Code.
Observed:
- Sandbox initialization fails with
bwrap: Can't mkdir /mnt/c/Program Files/ClaudeCode: Permission denied. - With
allowUnsandboxedCommands: true: Claude Code prints "Retrying without the sandbox" and runs the command unsandboxed. All subsequent commands do the same. - With
allowUnsandboxedCommands: false: sandboxed execution is entirely unusable.
Expected:
- Nonexistent managed-settings source paths should be skipped (stat before bind, or make the bind optional) — an absent enterprise-settings directory is the normal case for individual installs.
- If sandbox initialization fails, that should be surfaced prominently (persistent warning, or fail closed), not silently downgraded to unsandboxed execution per command. Silent fallback defeats the point of enabling the sandbox.
Workaround
Creating the directory on the Windows side (as admin) fixes it:
New-Item -ItemType Directory 'C:\Program Files\ClaudeCode'
After that, the bind mount succeeds and the sandbox initializes normally.
Additional notes
- The path comes from the hardcoded WSL managed-settings constant (
C8in the 2.1.223 binary), used to readmanaged-settings.jsonfrom the Windows side when running under WSL. - Suggested fixes: (a)
stat()the source and skip the bind when absent; (b) treat sandbox-init failure as an error state that is clearly reported to the user rather than a silent per-command downgrade, even whenallowUnsandboxedCommandsis true.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗