[BUG] Critical: Bash permission deny rule `Bash(rm:*)` bypassed by multi-line commands with leading comments
Environment
- Platform:
- [X] Anthropic API (Claude Code CLI)
- Claude CLI version: 2.1.78 (Claude Code)
- Operating System: macOS 26.3.1 (Tahoe)
- Terminal: Warp / iTerm2
Bug Description
The deny permission rule for Bash commands can be bypassed when rm (or presumably any denied command) is embedded in a multi-line bash script with comment lines preceding it.
Permission configuration (~/.claude/settings.json):
{
"permissions": {
"deny": [
"Bash(rm:*)"
]
}
}
This correctly blocks:
rm -rf /tmp/test.txt— BLOCKED ✅rm /tmp/test.txt— BLOCKED ✅echo "x" && rm -rf /tmp/test.txt— BLOCKED ✅rm -rf /tmp/test.txt && echo "done"— BLOCKED ✅# comment\nrm -rf /tmp/test.txt(2-line) — BLOCKED ✅
But this bypasses the deny rule and the file gets deleted:
# Comment line 1
# Comment line 2
echo "Removing file..."
rm -rf /tmp/test.txt
echo "Done"
Result: ALLOWED — file deleted ❌
Steps to Reproduce
- Add
"Bash(rm:*)"to thedenylist in~/.claude/settings.json - Ask Claude to create a temp file:
touch /tmp/test-bypass.txt - Ask Claude to run a multi-line command with 2+ comment lines before the
rm:
``bash``
# This is a comment explaining why
# Another comment line
echo "Deleting..."
rm -rf /tmp/test-bypass.txt
echo "Done"
- Observe that the command executes without a permission prompt
- Verify the file is gone:
ls /tmp/test-bypass.txt→ "No such file"
Expected Behavior
The deny rule Bash(rm:*) should block any Bash command containing rm, regardless of where rm appears in a multi-line script. The permission system should parse the full command text, not just match against the first line or the command prefix.
Actual Behavior
The deny rule only catches rm when it appears at or near the start of the command string. When rm is preceded by 2+ comment lines and/or echo statements on separate lines, the permission check does not detect it, and the command executes without prompting the user.
Security Impact
This is a security-relevant bypass of user-configured permission boundaries. A user who explicitly denies rm expects that Claude cannot delete files via the Bash tool under any circumstances. The multi-line bypass completely undermines this expectation.
The bypass was discovered accidentally during a git worktree cleanup operation — not through intentional testing. This means it can occur naturally in real workflows.
Additional Context
The pattern suggests the permission matcher may be doing a prefix/start-of-string check or only inspecting the first "command" in a multi-line script, rather than scanning the full command text for denied patterns.
A robust fix might involve:
- Splitting multi-line commands and checking each line independently
- Using a regex that matches
rmanywhere in the command string (with word boundaries) - Parsing the shell script into individual commands before matching
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗