Deny list does not override allow list — broader allow pattern defeats specific deny

Resolved 💬 3 comments Opened Apr 9, 2026 by benkruger Closed Apr 12, 2026

Bug

When Bash(git *) is in the allow list and Bash(git commit *) is in the deny list, git commit commands are auto-allowed. The deny entry has no effect.

Expected Behavior

Deny list entries should always take precedence over allow list entries. A specific deny pattern like Bash(git commit *) should block the command even when a broader allow pattern like Bash(git *) matches.

Observed Behavior

git commit -m "..." executes successfully despite being on the deny list, because the allow list pattern Bash(git *) matches first and auto-approves the command.

Reproduction

  1. Add Bash(git *) to the allow list in .claude/settings.json
  2. Add Bash(git commit *) to the deny list
  3. Ask Claude to run git commit -m "test"
  4. The command executes instead of being blocked

Impact

The deny list is the only mechanical enforcement that Claude cannot ignore. If allow overrides deny, there is no way to permit a broad category of commands while blocking specific dangerous subcommands within that category. Users must enumerate every safe subcommand individually to avoid the conflict — which is a viable workaround, but the precedence behavior is still wrong and surprising.

Workaround

Replace Bash(git *) with specific subcommand patterns (Bash(git status *), Bash(git diff *), etc.) so no allow pattern matches the denied command.

View original on GitHub ↗

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