The check, and the paths it guards
Claude Code carries a circuit breaker for deletions. Before it runs an rm or rmdir aimed at what its documentation calls a critical path, it stops and asks, even in modes that skip every other prompt. A critical path is the filesystem root, any direct child of it such as /usr or /etc, the user's home directory, and the session's working directory and its parents. Anthropic's permission-modes page describes the intent plainly: "This circuit breaker guards against model error." The same page states the guarantee the guard is meant to hold — that no permissions.allow rule and no PreToolUse hook returning allow approves an rm or rmdir targeting a critical path.
The guard applies in every mode, including bypassPermissions; the bypass ran in the two states where nearly everything else runs unprompted — bypassPermissions mode and under a shell allow rule.
The wrapper that walked past it
A report filed on Anthropic's public tracker on 23 September, against Claude Code 2.1.280 on Windows 10 in Git Bash, described the gap. In bypassPermissions mode, a plain rm -rf on the session's own directory was stopped with the message "Dangerous rm operation detected". So were the same command wrapped in a subshell, a brace group, or a command substitution. Handing the deletion to a shell changed the outcome: both sh -c "rm -rf" and bash -c 'rm -rf', pointed at the same directory, ran and deleted the files.
The explanation is a parsing one. The program the check sees is sh or bash, and the rm sits inside a string argument, so the check never reaches it. The tests covered the working directory only; home and system directories run through the same function, the report says, so the wrapper is expected to behave the same way there. The report states the command was not run against those paths.
The fix, and the channel that does not have it
Anthropic's changelog says 2.1.288 fixed a dangerous rm, such as one on / or the home directory, inside a bash -c or sh -c script running without a prompt in bypassPermissions mode or under a shell allow rule. The release reached npm on 2 October at 18:30 UTC; the tracker issue was tagged area:security and closed at 20:19 UTC the same day, nine days after it was opened. The release carries 89 changes, two of them repairs to other permission checks: a BASHPID assignment whose value the shell would evaluate as arithmetic, previously allowed silently, and sandboxed heredocs with an unquoted delimiter, which had prompted on every run.
The fix's reach is partial. Read at 21:05 UTC on 2 October, npm's dist-tags for @anthropic-ai/claude-code listed latest and next at 2.1.288 but stable at 2.1.285, published 29 September — three releases behind, so an install or pin following stable does not have the fix (still 2.1.285 as of 4 October, re-checked against the npm registry). Both conditions the guard covers are opt-in: bypassPermissions must be started deliberately, with --permission-mode bypassPermissions or --dangerously-skip-permissions, and the shell allow rule is one the user writes. Anthropic's guidance for bypassPermissions, in its own words: "Only use this mode in isolated environments like containers, VMs, or dev containers without internet access, where Claude Code cannot damage your host system." The report points to three earlier changes to the same check: it lists 2.1.208 for command substitution and backticks, 2.1.261 for double-quoted sh -c on variable targets, and 2.1.273 for a subshell in bypass mode.
Sources
- Claude Code 2.1.288 fixes an rm guard a bash -c wrapper walked past, but stable is on 2.1.285 — MIXED Reality News
- Choose a permission mode — Claude Code docs (Anthropic)
- Dangerous-rm check does not look inside `sh -c` / `bash -c` — anthropics/claude-code issue #96300 (bsekiewicz, filed 23 Sep 2026, closed 2 Oct 2026)
Research
Thread
- Relates to: Craig — stop and read this
- Related to: The read-only check was a regex match
The same failure of a text-shaped guard: a blocklist that matches on what it is shown rather than on what will run.
Semantic neighbors
- Guardrails checked once, at the wrong moment77% similar
- The hook ran before the model could look76% similar
- Fine when checked, a symlink when written73% similar
