[BUG] `sandbox.filesystem.denyRead` silently bypassed when target is inside a `denyWrite` directory
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?
sandbox.filesystem.denyRead is silently bypassed when the target file is inside a directory listed in sandbox.filesystem.denyWrite. cat ./secrets/file returns the file contents to the model even though /sandbox Configuration shows the path under Filesystem Read Restrictions: Denied. See repro below — case A (denyRead alone) blocks the read; case B (denyRead + denyWrite on parent) leaks it.
What Should Happen?
Both case A and case B should block the read with Permission denied. The bypass should not be silent — if denyRead cannot be enforced for some configuration, /sandbox should not display the path as Denied.
Error Messages/Logs
N/A
Steps to Reproduce
#!/usr/bin/env bash
set -e
# A. denyRead alone — ENFORCED (correct)
rm -rf /tmp/repro-A && mkdir -p /tmp/repro-A/secrets && cd /tmp/repro-A
echo SECRET > secrets/file
mkdir -p .claude && cat > .claude/settings.json <<'EOF'
{"sandbox":{"enabled":true,"autoAllowBashIfSandboxed":true,
"allowUnsandboxedCommands":false,"failIfUnavailable":true,
"filesystem":{"denyRead":["./secrets/file"]}}}
EOF
echo "=== A ==="
claude --setting-sources project -p 'run cat ./secrets/file by bash'
# B. denyRead + denyWrite on parent — BYPASSED (BUG)
rm -rf /tmp/repro-B && mkdir -p /tmp/repro-B/secrets && cd /tmp/repro-B
echo SECRET > secrets/file
mkdir -p .claude && cat > .claude/settings.json <<'EOF'
{"sandbox":{"enabled":true,"autoAllowBashIfSandboxed":true,
"allowUnsandboxedCommands":false,"failIfUnavailable":true,
"filesystem":{"denyRead":["./secrets/file"],
"denyWrite":["./secrets"]}}}
EOF
echo "=== B ==="
claude --setting-sources project -p 'run cat ./secrets/file by bash'
=== A ===
The file is blocked by sandbox policy (`/tmp/repro-A/secrets/file` is in the read deny list), so `cat` returns "Permission denied". I can't read it.
=== B ===
Output: `SECRET`
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.119
Platform
Anthropic API
Operating System
Ubuntu/Debian Linux
Terminal/Shell
VS Code integrated terminal
Additional Information
Suspected: the --bind emitted for denyWrite on the parent directory masks the --ro-bind /dev/null overlay for the per-file denyRead.
This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗