deniedPaths bypassed by Bash tool — security policy not enforced uniformly across tools

Resolved 💬 2 comments Opened Apr 10, 2026 by vsrinadh Closed Jun 4, 2026

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 deniedPaths protects 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:

  1. Pre-execution path extraction — parse the Bash command, extract file path arguments, check against deniedPaths before running. Imperfect but catches obvious cases (ls, cat, find, grep with explicit paths).
  2. Working directory restriction — run Bash inside a chroot or restrict the shell's view of the filesystem to non-denied paths.
  3. Post-execution output filtering — scan command output for content from denied paths before returning to the model. Hardest to implement reliably.
  4. At minimum, warn the user — when Bash command matches a denied path pattern, prompt the user for explicit one-time approval (similar to the ask policy) 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

View original on GitHub ↗

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