Deny list does not override allow list — broader allow pattern defeats specific deny
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
- Add
Bash(git *)to the allow list in.claude/settings.json - Add
Bash(git commit *)to the deny list - Ask Claude to run
git commit -m "test" - 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.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗