[BUG] WSL2: managed-settings.json makes the Bash sandbox build a Windows-side mask path with an empty username (/mnt/c/Users/.claude), breaking every command
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
One-line
On WSL2, the mere presence of /etc/claude-code/managed-settings.json makes the sandbox add a bind-mount mask for the Windows-side user config dir, but the path is built with an empty username — /mnt/c/Users/.claude instead of /mnt/c/Users/<user>/.claude. That's the admin-only C:\Users root, so bwrap fails with Can't mkdir … Permission denied and aborts every sandboxed command. With sandbox.failIfUnavailable: true, Claude Code won't start at all. Not fixable from user config.
Environment
- Claude Code 2.1.217 (latest;
claude updatesays up to date), native installer at~/.local/bin/claude - WSL2 (Ubuntu) on Windows 11; project on DrvFs (
/mnt/c/...) - Sandbox backend: bubblewrap
HOME=/home/<username>(correct),USERNAME=<username>,USERPROFILE=/mnt/c/Users/<username>in the shell
Symptom (every Bash tool call, ! prefix, and hooks)
```
bwrap: Can't mkdir /mnt/c/Users/.claude: Permission denied
/mnt/c/Users/.mcp.json
Also observed as the base collapses: , and (with USERPROFILE unset) /mnt/c/.mcp.json`.
The target should be the Windows user config C:\Users\<username>\.claude = /mnt/c/Users/<username>/.claude. Instead the username segment is empty → /mnt/c/Users/.claude.
Exact trigger (bisected)
- Managed file present → broken. Managed file absent → sandbox works fully from the project
.claude/settings.json(identicalsandbox.enabled: true, denies, credential scrub, domain lockdown). - Trigger is the presence of the managed file, independent of its contents across the variants tried. It is not the
env/CLAUDE_CODE_SUBPROCESS_ENV_SCRUBkey, notallowManagedDomainsOnly, notfailIfUnavailable.
Why it's a Claude Code bug, not a config problem (all verified)
- Not env-fixable.
USERNAME=<username>andUSERPROFILE=/mnt/c/Users/<username>are set (viaWSLENV=USERPROFILE/p:USERNAME), yet the mask username is still empty. ClearingWSLENVmakes it worse (/mnt/c/Users/→/mnt/c/), showing the base tracksdirname($USERPROFILE)while the username leaf is separately empty. Correct behaviour would be to use$USERPROFILEdirectly. - Not fixable by pre-creating the target. Creating
C:\Users\.claude(+ siblings) as writable dirs/files does not resolve it — bwrap still fails, so this is not merely a missing mountpoint. - Not cwd. Reproduces from a Linux-fs cwd (
~) too, as long as the managed file is deployed. - Not version. Reproduces on latest (2.1.217).
Root cause (hypothesis)
Under managed policy, Claude Code masks the settings/config sources so a sandboxed process can't tamper with them, and on WSL it includes the Windows-side user config dir. The Windows path is constructed as roughly dirname($USERPROFILE) + "/" + <username> with <username> empty in the sandbox-setup context, yielding /mnt/c/Users/.claude (the admin-only Users root). bwrap can't create a mountpoint there → hard abort.
Impact
- Bash sandbox unusable on WSL whenever managed settings are deployed.
- With
failIfUnavailable: true, Claude Code refuses to launch — so an org that enforces managed policy on WSL is fully blocked from running Claude Code. - Same family as the closed #26722 / #17727 and the
C:\Program Files\ClaudeCodemask issue, but this variant is triggered by managed-settings presence and adds an empty-username path bug.
Suggested fix
- Build the Windows-side config mask from
$USERPROFILEdirectly (don't recompose it fromdirname+ a possibly-empty username). - On WSL, if a mask target's mountpoint can't be created (DrvFs / admin-only root), skip that single mask with a warning instead of aborting the whole sandbox.
- Don't require masking Windows-side paths at all when running under WSL — the enforcement point is
/etc/claude-code/managed-settings.jsonon the Linux side.
Note on debug capture
The malformed bwrap argv is not surfaced by claude --debug or CLAUDE_CODE_DEBUG=1 (tested in -p mode; no sandbox/bwrap lines logged). Happy to run any trace flag a maintainer suggests to dump the exact bind-mount arguments.
Minimal repro
- WSL2, Claude Code 2.1.217, project on
/mnt/c/.... - Deploy a managed-settings.json to
/etc/claude-code/managed-settings.json(failure was independent of contents across the variants we tried). - Start
claude, run a Bash command →bwrap: Can't mkdir /mnt/c/Users/.claude: Permission denied. sudo rm /etc/claude-code/managed-settings.json, retry → works.
What Should Happen?
Either fix as suggested or provide a workaround to fix the sandbox with managed settings deployed.
Error Messages/Logs
Claude just keeps repeating that bash is dead or the sandbox is unusable. ! commands run into:
`bwrap: Can't mkdir /mnt/c/Users/.claude: Permission denied`
Steps to Reproduce
WSL2, Claude Code 2.1.217, project on /mnt/c/....
Deploy a managed-settings.json to /etc/claude-code/managed-settings.json (failure was independent of contents across the variants we tried).
Start claude, run a Bash command → bwrap: Can't mkdir /mnt/c/Users/.claude: Permission denied.
sudo rm /etc/claude-code/managed-settings.json, retry → works.
Claude Model
Opus
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
2.1.217
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
WSL (Windows Subsystem for Linux)
Additional Information
_No response_
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗