Permission system UX: compound command blocking, rule accumulation, undiscoverable Bash(*) fix
Summary
The permission system has a compounding UX problem that makes "autonomous" agent usage impractical for long-term users. After 3 months of daily use, I accumulated 150+ narrow permission rules in settings.local.json — and compound commands (cd /my/project && git status) still prompted for approval every time because they don't match the individually-allowed patterns.
This is not one bug — it's a system-level UX failure across permission matching, compound command handling, and discoverability.
The Experience
- Month 1: Click "Always allow" on every
git status,ls,python script.pyprompt. Accumulate 50+ rules. - Month 2: Still getting prompted on compound commands. Click "Allow" hundreds more times. 100+ rules now.
- Month 3: 150+ rules. Compound commands STILL prompt with security warnings like "bare repository attack prevention" — on my own project directory that I've been working in for months. Agent autonomy is fiction.
- Discovery: Learn about
Bash(*)from reading source code. Replace 150 rules with 8 broad wildcards. Problem solved instantly. This should have been offered on day 1.
The Four Compound Command Blockers
These fire constantly when working in your own trusted project:
- "Compound commands with cd and git require approval to prevent bare repository attacks"
- "Compound command contains cd with output redirection - manual approval required to prevent path resolution bypass"
- "Compound commands with cd and git require approval" (variant)
- General compound command security checks
These assume adversarial scenarios (cloning untrusted repos, path traversal) that don't apply to users working in their own project root. They cannot be disabled without discovering Bash(*).
Evidence: My settings.local.json Before Cleanup
150+ entries including:
- Every individual command:
Bash(python:*),Bash(git status:*),Bash(ls:*),Bash(cd:*),Bash(git log:*), etc. - One-off commands that got permanently saved:
Bash(RUN_OVERNIGHT_ANALYSIS.bat core), individualforloop fragments, multi-line Python heredocs with full escaped source code as permission patterns - Compound commands that were allowed once but the pattern was too specific to match again
Despite all of this, cd /project && git status still prompted.
The Fix (Trivial but Undiscoverable)
{
"permissions": {
"allow": ["Bash(*)", "Read(*)", "Write(*)", "Edit(*)", "Glob(*)", "Grep(*)"],
"ask": ["Bash(rm -rf:*)", "Bash(git push --force:*)", "Bash(git reset --hard:*)"]
}
}
8 rules replace 150+. Dangerous commands still prompt. Everything else just works. Real safety comes from hooks (RAM auditing, pre-commit validation), not permission prompts on ls.
Related Issues (13 reports, same root cause)
Compound command blocking:
- #28183 — Compound commands of individually-allowed commands still prompt
- #29491 — Compound bash commands should evaluate each command's permissions independently
- #20985 — Feature request for smart permission matching on compound shell commands
- #30435 — Feature request to suppress bash safety heuristic prompts via settings
- #30524 — Windows: unnecessary
cdprepended to commands triggers bare repository prompt
Permissions not sticking / wildcards broken:
- #27139 — Broad wildcard permissions in settings.local.json not respected
- #29400 — "Don't ask again" doesn't persist
- #11380 — Continually asks for permission after "always allow"
- #10629 — Asking permission too often
- #3428 —
Bash:*wildcard not working
Trust model:
- #29285 — Feature request to permanently trust a directory
- #28784 — Security:
Bash(cd:*)allows arbitrary execution via&&chaining
Token injection:
- #15742 — Multi-line bash
__NEW_LINE__token appears in saved permission patterns
Proposed Solutions
- Offer "trust this project" during first session — a first-class option that sets
Bash(*)+ dangerous-onlyasklist - Make
Bash(*)discoverable — surface it in/permissions, in the "Always allow" dialog, and in docs - Compound command permissions should decompose —
cd /path && git statusshould checkBash(cd:*)ANDBash(git status:*)individually, not treat the compound as a new unique pattern - Scope security checks to actual risk — bare repository attack protection should only apply when entering directories outside the project root, not when
cd-ing within your own working tree - Periodic permission cleanup prompt — after 50+ rules accumulate, suggest consolidation
Environment
- Claude Code v2.1.70
- Windows (MSYS2/Git Bash)
- Daily user since December 2025
- 11 custom agents, hooks for RAM safety / pre-commit / compaction recovery
This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗