deniedPaths bypassed by Bash tool — security policy not enforced uniformly across tools
Summary
The deniedPaths setting in ~/.claude/settings.json is enforced for the Read/Edit/Write tools but bypassed by the Bash tool. Any shell command (ls, cat, grep, find, etc.) can read files inside denied paths because the permission check inspects the command name, not the paths the command accesses.
This makes deniedPaths a false sense of security — users can set a deny boundary, but it leaks through any approved Bash command.
Reproduction
~/.claude/settings.json:
{
"permissions": {
"ask": ["Read", "Bash", "Edit", "Write"]
},
"deniedPaths": [
"/Users/example/**"
]
}
Behavior:
| Tool call | Path | Expected | Actual |
|---|---|---|---|
| Read /Users/example/secret.txt | matches deny | denied | denied ✓ |
| Bash ls /Users/example/ | matches deny | denied | allowed ✗ |
| Bash cat /Users/example/secret.txt | matches deny | denied | allowed ✗ |
| Bash grep -r 'token' /Users/example/ | matches deny | denied | allowed ✗ |
The Bash tool only checks if "Bash" itself is in the permissions list (ask/allow). It does not parse the command to detect file paths and cross-reference them against deniedPaths.
Impact
- Security: Users believe
deniedPathsprotects sensitive directories. It only protects against direct Read/Edit/Write tool calls. Any agent using shell utilities can read denied content freely. - Consistency: A "denied" path should be denied regardless of which tool is used to access it. The current behavior breaks the principle of least surprise.
- Auditability: Bash command outputs containing sensitive content end up in conversation history and logs, defeating the original intent of the deny list.
Expected behavior
deniedPaths should be enforced for all tools that can read or write files, including Bash. Possible implementations:
- Pre-execution path extraction — parse the Bash command, extract file path arguments, check against
deniedPathsbefore running. Imperfect but catches obvious cases (ls,cat,find,grepwith explicit paths). - Working directory restriction — run Bash inside a chroot or restrict the shell's view of the filesystem to non-denied paths.
- Post-execution output filtering — scan command output for content from denied paths before returning to the model. Hardest to implement reliably.
- At minimum, warn the user — when Bash command matches a denied path pattern, prompt the user for explicit one-time approval (similar to the
askpolicy) instead of running silently.
Workaround
Users currently have to manually inspect each Bash command before approving and reject anything that touches denied paths. This defeats the automation deniedPaths was meant to provide.
Environment
- Claude Code (latest as of 2026-04-09)
- macOS Darwin 25.3.0
🤖 Generated with Claude Code
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗