trailofbits / trailofbits/claude-code-config

`rm -rf` hook does not catch `find -exec rm -rf` or `xargs rm -rf`

Open Beginner friendly
#58 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Shell
Stars
2.1k
Forks
161
Avg merge
3d 59m
Merged PRs (30d)
1

Description

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.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Open settings.json at line 55 and inspect the existing rm -rf PreToolUse pattern; compare its behavior with the find -exec, xargs, and newline examples in the issue. Check README.md at line 236 for the guardrail framing, then make the chosen coverage or documentation change. Done means the reported indirect forms are either handled or explicitly documented as gaps.

Written by the indexing model from the issue text.

Assessment

Tech stack
bash, shell
Domain
cli, security
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.