AI Briefing
KOSign in

Claude Code PreToolUse Hooks Fail Open on Errors, Creating Security Risks

·2026.10.05 02:25

Key point

PreToolUse hooks in Claude Code only block actions on exit code 2, allowing dangerous commands like rm -rf to proceed if the hook script crashes or times out.

Details

A correction to a previously shared PreToolUse hook reveals that the original implementation fails open. Only exit code 2 blocks a hook's action; any other exit code (such as 1 from a Python crash or 127 from a missing dependency) is treated as a non-blocking error, allowing the command to proceed through the normal permission flow.

Security Implications

This behavior is critical in auto mode, where a classifier approves actions instead of the user. If a hook fails due to:

  • Unparseable input (causing a Python crash)
  • Timeouts (default 10 minutes)
  • Missing dependencies (e.g., jq not installed, python3 not on PATH)
  • Incorrect exit codes (e.g., sys.exit("Refused") exits 1)

...the safety guard is bypassed, and commands like rm -rf execute without intervention.

Recommended Fix

To ensure safety, hooks must fail closed. The fixed version uses a try/except block to force exit code 2 on any error:

!/usr/bin/env python3
import json, re, sys
try:
    command = json.load(sys.stdin).get("tool_input", {}).get("command", "")
    if re.search(r"\brm\s+-[a-zA-Z]*[rR]", command):
        print("Recursive rm is blocked. Do not try another way; ask the user to run it.", file=sys.stderr)
        sys.exit(2)
except Exception as error:
    print(f"Guard failed ({type(error).__name__}), refusing.", file=sys.stderr)
    sys.exit(2)

Developers should test failure cases (e.g., piping invalid JSON) to ensure the hook returns 2, accepting the trade-off that a broken hook will refuse all Bash calls until fixed.

This summary was generated automatically by AI. Check the original for the author's claims and context. Copyright belongs to the original author.

Our guide explains how the AI works. Report summary errors, attribution issues, or removal requests via Contact.