AIToday
AI Coding AssistantsAI Safety & AlignmentZenn AI/MLPublished: Oct 20, 2026, 13:00 JST

Claude Code hooks stop rm -rf, but rm -fr slips through

Claude Code hooks stop rm -rf, but rm -fr slips through

3 Key Points

  1. What happened

    In a real Claude Code 2.1.304 session, a PreToolUse hook script blocked 'rm -rf build' with exit code 2, but 'rm -fr build' ran and deleted the folder, and the author lists many bypasses such as 'rm -r -f' and 'find build -delete'.

  2. Why it matters

    The hook only pattern-matches command strings, so it works as an early net for common dangerous forms rather than a sandbox; the author says to pair it with permission settings and pre-work git commits.

Not sure about something? Ask the AI

Questions and answers are published on this page.

Summaries like this, in your inbox every morning.

Context & Analysis

The test was run in a disposable folder with claude -p, the non-interactive mode, and with --dangerously-skip-permissions so that per-command approvals would not interfere; the author explicitly warns not to use that option in normal work. Even with approvals skipped, the hook returning exit code 2 stopped the command, and the error text was passed back to Claude. The author also tested the script standalone by feeding it JSON in the same shape Claude Code provides. That standalone run showed 'git push --force origin main' and 'git reset --hard HEAD~3' were stopped, while 'rm -fr build' and 'rm -r -f build' passed; the latter two were not tried in a live session.

The script depends on jq to read the command, and the author shows why the 'command -v jq' line matters. Without it, an environment missing jq would read nothing and exit 0, letting everything through — and because the exit code is 0, onFailure would not treat it as a failure. Removing jq from PATH in a real session, the version with the check blocked even 'ls build' with a 'jq is required' message, while the version without it let 'rm -rf build' delete the folder.

The onFailure setting was introduced in version 2.1.295, and in 2.1.294 a wrong script path did not stop the command. The author tested only the missing-script case and notes that the documentation also counts non-0/2 exit codes, timeouts, and unreadable JSON output as failures. The closing advice is to use permission settings for commands that must be blocked reliably, keep the hook as an early net, and confirm behavior in a dummy folder before trusting it.

FAQ
Why did 'rm -fr build' get through when 'rm -rf build' was blocked?
The hook script searches the command string for literal patterns like 'rm -rf'. Reordering the flags to 'rm -fr' no longer matches, so the script exits 0 and the command runs.
What does the onFailure setting do?
It was added in Claude Code 2.1.295. With 'onFailure: "block"', if the hook script cannot start or fails, the tool call is blocked instead of passing through.
What should I check before relying on a hook like this?
The author says to confirm Claude Code is version 2.1.295 or later, and to test with a dummy folder by asking for rm -rf to verify it is actually blocked.

AI news that matters for your work, delivered every morning.

Pick your industry and the AI tools you use, and get news related to your work every day.

Free · 30 seconds with Google · unsubscribe anytimeWhat is AIToday? →

Ask AI

Ask AI anything about this article. The AI reads this article, earlier AIToday articles, and Wikipedia, and cites its sources. Q&As are published on this page for other readers too.

Questions and answers are published on this page.

Related Articles

Next articleMamdani: AI not inevitable, feds abdicated on rules