[BUG] ask list is ignored when "Bash" is in allow list
Environment
- Platform (select one):
- [X] Anthropic API
- [ ] AWS Bedrock
- [ ] Google Vertex AI
- [ ] Other: <!-- specify -->
- Claude CLI version: Latest (as of 2025-08-25)
- Operating System: Linux
- Terminal: Terminal App
Bug Description
The ask list in permissions is completely ignored when "Bash" is in the allow list, making it impossible to implement a "allow all commands except require confirmation for destructive ones" permission model at the user level.
Steps to Reproduce
- Set user-level configuration in
~/.claude/settings.json:
``json``
{
"permissions": {
"allow": ["Bash"],
"ask": ["Bash(rm *)", "Bash(git push*)", "Bash(git branch*-D*)"]
}
}
- Ensure no project-level overrides exist (empty or no
.claude/settings.jsonin project) - Restart Claude Code completely
- Run:
touch test.txt && rm test.txt
Expected Behavior
The rm command should trigger a confirmation prompt because it matches the "Bash(rm *)" pattern in the ask list, despite "Bash" being in the allow list.
Actual Behavior
The file is deleted immediately without any confirmation prompt. All commands matching patterns in the ask list execute without prompting.
Additional Context
Goal: Single user-level configuration for "bypass all permissions except blacklisted destructive commands" across all projects.
Impact: No way to achieve both convenience (no prompts for safe commands) and safety (protection against destructive commands).
Workarounds attempted (none work):
defaultMode: "bypassPermissions"- Bypasses everything including ask listdefaultMode: "default"- Prompts for every new command type
22 Comments
---
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
---
I'm encountering this as well. I have the following
settings.json:mkdir -p foo && touch foo/bar.txtin the terminal.Bash(rm -rf foo), with no prompt appearing, despite the command matching my last two "ask" rules.Same thing:
but it will still run
curlcommands if I ask it to.We are essentially asking for "allow all Bash commands except some" and that isn't currently being honored.
This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.
Still a problem.
Still a problem.
Still a problem. Has anyone ever seen the Claude team fix any of these issues?
I filled this: https://github.com/anthropics/claude-code/issues/19501
but looks the same
Also facing this issue. Want to require asking before recursive removal just to be safe
Same here. I just want to confirm
rm -rf+1
I'm on MacOS using Claude Code CLI and am also facing this issue.
https://claude.ai/install.shmethodFor the love of god please fix this
As a workaround, I think a PreToolUse or PermissionRequest hook could acheive this kind of behavior. You'd remove Bash from your allow list in settings.json, and then make the hook decide to allow things as long as they don't match any of your "ask" rules.
Another approach is "LLM as guardrail": a
PreToolUseprompt hook sends every Bash command to a (fast) model judging whether the command would have negative side effects. If negative side effects are predicted, user confirmation is needed. This can be used along a block list, but would be more general.+1
+1.
Simplest possible repro:
Settings (.claude/settings.json)
```json
{
"permissions": {
"allow": ["Bash(*)"],
"ask": ["Bash(echo*)"]
}
}
Steps to reproduce
The permission system's
allow+askinteraction has been a pain point for a while. Here's a pattern that works today usingPreToolUsehooks to get exactly the behavior described (allow all bash, block specific dangerous commands):settings.json:
destructive-guard.shreads the command from stdin JSON, checks against patterns like dangerousrminvocations,git reset --hard,git clean -fd, and exits with code 2 (hard block) when matched. Exit 0 = allow.Minimal example:
This gives you "allow everything except these specific dangerous commands" — which is what
askshould have done but doesn't when combined withallow.The hook approach is actually more flexible than the permission system because you can add mount-point detection (prevent rm on paths with NFS mounts), force-push blocking,
.envstaging prevention, etc.npx cc-safe-setupinstalls a production-tested set of these guards if you want a ready-to-go solution.The
asklist being ignored whenBashis inallowis a known interaction bug. A hook gives you precise control:Three tiers:
ls,cat,grep,git— auto-approved viapermissionDecision: "allow"rm,mv,docker— hook exits silently, normal prompt appearssudo,shutdown—exit 2blocks unconditionallyThis replaces the broken allow/ask/deny interaction with reliable hook-based logic.
Same root cause, deny variant (more safety-critical): if you have allow: ["Bash(git:*)"] and deny: ["Bash(git
status)"], the deny is completely ignored — git status runs without any prompt. Removing the broader allow rule from
the allow list restores deny behavior.
Repro (Windows, Claude Code desktop, PowerShell/bash):
{
"permissions": {
"allow": ["Bash(git:*)"],
"deny": ["Bash(git status)"]
}
}
Run git status — executes freely, no prompt, deny rule ignored. Remove "Bash(git:*)" from allow, run again — now
correctly blocked/prompted.
The deny case matters more than ask: documentation says deny wins over allow unconditionally. If allow beats deny,
there's no safe way to build an allowlist with carve-outs for dangerous commands. Verified on 2026-05-10, Claude Code
Windows desktop app.
Claude code wrote these - btw...
To add to my previous comment: I want to flag the security severity of the deny bypass specifically.
The documented contract is that deny is an unconditional block — the docs state "deny wins over allow." Users
reasonably rely on this to protect against catastrophic commands. A typical real-world setup:
{
"permissions": {
"allow": ["Bash"],
"deny": [
"Bash(rm -rf *)",
"Bash(DROP TABLE*)",
"Bash(DROP DATABASE*)"
]
}
}
A user who reads the docs and configures this believes they've protected their database. They haven't — the deny rules
are silently ignored because Bash is in allow. Claude Code will run DROP DATABASE mydb without any prompt or warning.
This isn't a UX issue — it's a security bypass. The permission system is advertising safety guarantees it doesn't
deliver, which is worse than having no safety guarantee at all (because at least then users would know to rely on
something else).
Workarounds via PreToolUse hooks exist (see comments above) but require bash scripting skills and aren't discoverable
by users who trusted the documented behavior. The fix needs to be in the core permission system: deny must win over
allow, unconditionally, exactly as documented.
I will also send this to security@anthropic.com for triage as a security issue rather than a feature gap.
@jbert50021 did you end up contacting the security team?
From my research, an allow Bash(*) by the user even works when
allowManagedPermissionRulesOnlyis set. From my point of view,allowManagedPermissionRulesOnlyis useless at the moment and there is no way for an organization to control user-side permissions besides hooks.