-
Notifications
You must be signed in to change notification settings - Fork 7.1k
Description
Summary
The permission matching system doesn't work. It's been broken since mid-2025, there are 30+ open issues about it, and Anthropic staff have left one comment across all of them — a workaround suggestion in September 2025 that didn't fix anything.
The community is now writing custom PreToolUse hooks in Python to reimplement permission enforcement from scratch (#18846). That's where we are.
What's broken
I have 136 allow rules, 2 deny rules, and 31 ask rules in my settings.json. Carefully segmented by risk. I still get prompted constantly for commands that should match.
Wildcards don't match compound commands (#25441, #29616, #29529). Bash(git:*) doesn't match git add file && git commit -m "message". The * only works within a single simple command. Claude generates compound commands constantly, so the wildcards are useless in practice.
"Always Allow" saves dead rules (#6850, #11380). Click "Always Allow" on git commit -m "fix typo" and it saves that exact string — commit message and all. Never matches again. Over time settings.local.json fills up with hundreds of one-off rules while the actual wildcard patterns sit there unused.
User-level settings don't apply at project level (#5140, #18160). Rules in ~/.claude/settings.json show up in /permissions but don't match anything. Same rules in project-level settings.local.json reportedly work fine.
Quote-tracking bypasses the allow list entirely (#30345). Commands with quotes in # comments trigger a safety warning that ignores all allow rules. Filed on v2.1.63, which is current.
Deny rules have the same bugs (#25441 comments, #18613). Multiline commands bypass deny rules too. Flag reordering can also get around them. So the permission system isn't just annoying — it's not enforcing the safety constraints users configured.
Colon vs space syntax is contradictory (#30113). Bash(git:*) and Bash(git *) behave differently. The docs don't agree on which is correct. "Always Allow" generates one syntax, users configure the other.
The security problem
Users who care about permissions have three options right now:
- Click through every prompt without reading. Defeats the purpose.
- Switch to
bypassPermissions. Disables everything including deny rules. - Build custom hooks to reimplement matching.
Option 3 is what people are actually doing. Community-built Python scripts with no security review, no tests against adversarial inputs, no correctness guarantees. The first-party permission system exists so users don't have to do this.
Staff engagement
| Issue | Filed | Problem | Staff response |
|---|---|---|---|
| #5140 | Aug 2025 | User settings not applied at project level | None |
| #6850 | Aug 2025 | Allow list not working, dead rules accumulating | One workaround (didn't fix it) |
| #11380 | Nov 2025 | Prompts despite "Always Allow" | None (oncall label) |
| #18160 | Jan 2026 | Allow permissions ignored | None |
| #18846 | Jan 2026 | Permissions not enforced at all | None |
| #25441 | Feb 2026 | Wildcards don't match multiline | None |
| #29187 | Feb 2026 | "Always Allow" suggests wrong patterns | None (labeled regression) |
| #29616 | Feb 2026 | Wildcard patterns don't match | None |
| #30113 | Mar 2026 | Contradictory documentation | None |
| #30345 | Mar 2026 | Quote-tracking bypasses allow list | None |
No milestones. No Anthropic-authored PRs. No roadmap. No tracking issue.
What we need
-
A staff response. Even just "we know, it's on the roadmap for Q3" would change the dynamic. 30+ issues spanning 7 months with silence is not a good look for a security-relevant subsystem.
-
Compound command matching.
Bash(git:*)should matchgit add && git commit. Single-command-only matching doesn't reflect how Claude actually generates bash. -
Smarter "Always Allow." Approving
git commit -m "fix typo"should saveBash(git commit:*), not the verbatim string. -
Scope enforcement that works. User-level rules should match everywhere they show up.
-
Deny rules that hold. No variation of a denied command — multiline, reordered flags, embedded in a chain — should execute without prompting.
-
One clear document covering syntax, matching semantics, scope hierarchy, and known limitations.
-
A tracking issue so the community can follow progress instead of filing duplicates.
Environment
- Claude Code v2.1.63
- macOS Darwin 24.6.0
- 136 allow, 2 deny, 31 ask rules in
~/.claude/settings.json defaultMode: "acceptEdits"- Running a
PermissionRequesthook as a workaround
Related issues
#5140, #6850, #11380, #18160, #18613, #18846, #25441, #27688, #29187, #29529, #29616, #30113, #30345