[BUG] Headless claude -p with sandbox: every Bash call fails "bwrap: Can't create file at /home/.mcp.json" — profile binds ancestor .mcp.json candidates unconditionally

Status Closed — duplicate
Reported on v2.1.221
Maintainer reply None cached
Activity 2 comments · opened Aug 4, 2026 · closed Aug 15, 2026

Environment

  • claude-code 2.1.221, Linux (bubblewrap sandbox); observed with claude-fable-5 and claude-opus-5 (model-independent)
  • Headless claude -p subprocess; cwd is a detached git worktree deep under $HOME (~/.cache/<harness>/worktrees/<task>/<run>/<candidate>)
  • Inline --settings: {"sandbox": {"enabled": true, "failIfUnavailable": true, "allowUnsandboxedCommands": false, "network": {"allowedDomains": [], "strictAllowlist": true}}, ...}
  • Command line includes --strict-mcp-config and --disallowedTools mcp__*; env has CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1; HOME is set normally

Symptom

Every Bash tool call fails immediately at sandbox setup:

Exit code 1
bwrap: Can't create file at /home/.mcp.json: Permission denied

All other tools (Read/Edit/Write/Glob/Grep) work; the session otherwise completes. Interactive sessions on the same machine sandbox Bash fine.

Root cause (as far as we could establish)

The bwrap profile generated for each Bash command includes bind directives for .mcp.json discovery candidates at every ancestor directory of cwd. When the bind target's parent is not user-writable (/home is root-owned), bwrap cannot create the target and aborts before the command starts.

Two empirical datapoints that sharpen this:

  1. --strict-mcp-config does NOT suppress the ancestor binds (it only affects MCP config loading).
  2. The walk is not first-found-wins: with a project-local .mcp.json ({"mcpServers": {}}) present in cwd during the run, all Bash calls still failed on the identical /home/.mcp.json bind — the profile binds every ancestor candidate unconditionally. (Also note cwd was a git worktree whose .git is a gitdir-pointer file; if discovery is meant to stop at a repo boundary, it does not here.)

Reproduction

mkdir -p ~/.cache/repro/deep && cd ~/.cache/repro/deep
claude -p --settings '{"sandbox":{"enabled":true,"failIfUnavailable":true}}' \
  --strict-mcp-config --disallowedTools 'mcp__*' \
  'Run `echo test` with the Bash tool and report the output.'
# => bwrap: Can't create file at /home/.mcp.json: Permission denied

(Requires a machine where /home is root-owned — the Linux default.)

Related open issues

Structurally similar bwrap profile failures: #80212 (WSL2 inaccessible-path bind), #50781 (sandbox policy self-conflict at init), #17258 (phantom dotfiles), #44567 / #40133 (worktree/symlink binds).

Requested fix (any of)

A. Skip ancestor bind targets whose parent directory is not user-writable (or bind only candidates that exist).
B. Make --strict-mcp-config also suppress ancestor .mcp.json discovery binds — the flag's contract is "only use MCP servers from --mcp-config".
C. Stop the discovery walk at the enclosing repository boundary, including worktrees whose .git is a gitdir-pointer file.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗