[BUG] Sandbox masking of nonexistent ~/.claude/.config.json creates a transient empty file visible system-wide; concurrent sessions fail with 'contains invalid JSON'
Summary
When the Bash-tool sandbox masks ~/.claude/.config.json (part of the default filesystem deny list) and that file does not exist, sandbox setup creates a real zero-byte, mode 0444 file at the real path to serve as a bind-mount point for /dev/null, and deletes it again at teardown. For the whole duration of the sandboxed command this empty file is visible to every other process on the machine. Any claude process that starts inside that window reads the empty file and aborts the config load with:
The configuration file at /home/<user>/.claude/.config.json contains invalid JSON.
With several parallel sessions (each running sandboxed Bash commands regularly), these windows are frequent, so the error appears seemingly at random when opening or resuming sessions. The file's absence is the normal state on this install — Claude Code 2.1.220 itself never creates it — so the error is always a false positive caused by the sandbox's own placeholder.
Environment
- Claude Code 2.1.220 (native install,
autoUpdatesChannel: latest); also observed on 2.1.212 - Ubuntu 24.04.4 LTS, kernel 7.0.0-28-generic
- Sandbox enabled (default
sandbox.network/filesystem settings;~/.claude/.config.jsonis in the built-in write-deny set)
Reproduction
- Ensure
~/.claude/.config.jsondoes not exist. - In session A, run any long sandboxed Bash command, e.g.
sleep 30. - While it runs, from a plain shell:
````
$ ls -la ~/.claude/.config.json
-r--r--r-- 1 user user 0 Aug 1 11:46 /home/user/.claude/.config.json
- Start a new
claudesession (orclaude -p ...) while the command is still running → the "contains invalid JSON" error is printed at startup. - Let the sandboxed command finish → the file disappears:
````
$ ls -la ~/.claude/.config.json
ls: cannot access '/home/user/.claude/.config.json': No such file or directory
Inside the sandbox the same path appears as a character device 1:3, i.e. the /dev/null bind mount over the placeholder:
$ ls -la ~/.claude/.config.json # from within a sandboxed command
crw-rw-rw- 1 nobody nogroup 1, 3 Aug 1 05:49 /home/user/.claude/.config.json
Expected behaviour
Masking a path that does not exist should not materialise a world-readable empty file at the real location. Options: create the mount point inside a private mount namespace only, mount over a tmpfs stub, or treat a missing deny-list target as "nothing to mask".
Impact
- Spurious "invalid JSON" startup errors whenever a session starts concurrently with any sandboxed command in any other session. Misleading: it looks like config corruption and invites users to "repair" a file that does not actually exist.
- Suspected, not verified: repeated
~/.claude/backups/.claude.json.backup.<epoch>files are written in bursts that coincide with these windows, suggesting sessions also trigger backup/recovery logic off the phantom empty config.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗