[BUG] Security: permissions.deny rules not working
Status Open
Reported on v2.1.140
Maintainer reply ✓ Yes — ant-kurt
Workaround ✓ Mentioned in thread ↓
Activity 6 comments · opened May 21, 2026
💡 Likely answer: A maintainer (ant-kurt, collaborator)
responded on this thread — see the highlighted reply below.
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?
Claude can read an example.key file (or any other key file) inside the project directory even if the ~/.claude/settings.json clearly forbids that:
{
"theme": "auto",
"model": "opus",
"sandbox": {
"enabled": true,
"failIfUnavailable": true,
"allowUnsandboxedCommands": false,
"autoAllowBashIfSandboxed": false,
"filesystem": {
"denyRead": ["//**"],
"allowRead": [
"~/Sites/example"
]
}
},
"permissions": {
"deny": [
"Read(/**/*.key)"
]
}
}
What Should Happen?
Claude should not be able to read those sensitive files, and should respect permissions.
Error Messages/Logs
Steps to Reproduce
- Create that
~/.claude/settings.jsonfile with the content above - Create an
example.keyfile in the project directory - Ask Claude to read that file
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.140 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
_No response_
Showing cached comments. Read the full discussion on GitHub ↗
5 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Seems to work with
"Read(//**/*.key)"instead of"Read(/**/*.key)"...In any case this looks like a bug or something not documented properly.
While this is open, here's a drop-in PreToolUse-hook workaround that enforces the deny rules until the native path is fixed:
https://github.com/moizxsec/claude-deny-guard
.env/ key / secret deny globs across Read / Edit / Write / MultiEdit / NotebookEdit and Bash (blockscat .env,curl, etc. by command regex or denied-path reference).settings.jsonfrom Edit/Write, so Claude can't disable its own guard.allowdecision — on a pass it stays silent and exits 0, so it doesn't suppress the native permission prompt for other tools.permissionDecision: "deny"JSON and exit code 2, for old/new clients.Honest limitation: Bash matching is token-based, so a deliberately obfuscated command can slip past — it raises cost, not a sandbox. But it closes the common
.env/secret-read cases today. Rules/PRs welcome.Closing for now — inactive for too long. Please open a new issue if this is still relevant.
Reopening — this is a real bug and not a duplicate of #61208 (that one is about confining reads to a region; this one is about a more specific deny inside an allowed region).
Two things are going on in the report:
Read(/**/*.key)with a single leading slash is resolved relative to the settings file's directory;Read(//**/*.key)(double slash) is filesystem-root-anchored, which is what you found. That part is working as documented, though it's clearly easy to trip over.//**/*.key, the built-in Read tool is blocked, but on macOS a sandboxed Bash command (cat example.key) can still read the file when it's inside asandbox.filesystem.allowReadregion: the sandbox profile emits the wildcard deny before the allowRead rule and macOS applies the last matching rule. Literal (non-wildcard) denies were already fixed; wildcard denies were not. Linux is not affected.A fix is in progress in the sandbox runtime; this issue will be updated with the Claude Code version that includes it.