The rm -rf PreToolUse hook in settings.json:55 only recognizes rm at the start of the command string or immediately after ;, &&, ||, or |:
(^|;[[:space:]]*|&&[[:space:]]*|[|][|][[:space:]]*|[|][[:space:]]*)rm[[:space:]]
It doesn't catch the two forms an agent produces most naturally when told to clean up a tree:
find . -name '*.tmp' -exec rm -rf {} \;
find . -name '*.tmp' | xargs rm -rf
Neither has rm in a recognized position, so both pass. An rm after a newline in a multi-line command also passes.
README.md:236 frames hooks correctly as "guardrails, not walls," so this isn't a security boundary failing — but -exec and xargs are the first two shapes anyone hits, which makes the guardrail easy to over-trust.
Suggested fix
Either extend the position set to cover -exec and xargs (and a newline), or note the gap in the README so nobody assumes the hook covers indirect invocations.
Related: #48 identifies the same class of gap from the permissions side — deny rules not covering indirect writes. And #33 applied this kind of rigor to this hook already; this is two shapes that pattern didn't reach.
Aside
The permissions.deny entries Bash(rm -rf *) / Bash(rm -fr *) also don't cover rm -r -f, rm -Rf, or rm --recursive --force. Anthropic's docs do warn that argument-matching Bash patterns are inherently fragile, so the hook is the layer that matters — noting it only so the deny list isn't mistaken for coverage.
Found while reviewing the repo against Anthropic's current docs and the installed CLI (2.1.238). One of five separate findings from the same pass.
The
rm -rfPreToolUse hook insettings.json:55only recognizesrmat the start of the command string or immediately after;,&&,||, or|:It doesn't catch the two forms an agent produces most naturally when told to clean up a tree:
Neither has
rmin a recognized position, so both pass. Anrmafter a newline in a multi-line command also passes.README.md:236frames hooks correctly as "guardrails, not walls," so this isn't a security boundary failing — but-execandxargsare the first two shapes anyone hits, which makes the guardrail easy to over-trust.Suggested fix
Either extend the position set to cover
-execandxargs(and a newline), or note the gap in the README so nobody assumes the hook covers indirect invocations.Related: #48 identifies the same class of gap from the permissions side — deny rules not covering indirect writes. And #33 applied this kind of rigor to this hook already; this is two shapes that pattern didn't reach.
Aside
The
permissions.denyentriesBash(rm -rf *)/Bash(rm -fr *)also don't coverrm -r -f,rm -Rf, orrm --recursive --force. Anthropic's docs do warn that argument-matching Bash patterns are inherently fragile, so the hook is the layer that matters — noting it only so the deny list isn't mistaken for coverage.Found while reviewing the repo against Anthropic's current docs and the installed CLI (2.1.238). One of five separate findings from the same pass.