#!/bin/bash # pre-tool-use.sh: Block dangerous shell commands before Claude executes them. # # Claude Code calls this script BEFORE executing any Bash command. # The script receives a JSON object on stdin with two fields: # - tool_name: the name of the tool being called (e.g., "Bash") # - tool_input: the arguments passed to the tool (e.g., {"command": "ls -la"}) # # Exit codes: # 0 Allow the command to proceed # 2 Block the command (Claude receives the "reason" field as an error message) # # When blocking, write a JSON object to stdout: # {"decision": "block", "reason": "Human-readable explanation"} # # Make this script executable: chmod +x hooks/pre-tool-use.sh # Read the full JSON payload from stdin input=$(cat) # Extract tool_name and the command argument from the JSON tool_name=$(echo "$input" | python3 -c "import sys,json; print(json.load(sys.stdin).get('tool_name',''))" 2>/dev/null) command=$(echo "$input" | python3 -c "import sys,json; print(json.load(sys.stdin).get('tool_input',{}).get('command',''))" 2>/dev/null) # Only inspect Bash tool calls. Allow everything else immediately. if [ "$tool_name" != "Bash" ]; then exit 0 fi # Each blocked pattern is checked separately with a descriptive reason. # Pattern matching uses grep -qiE (case-insensitive extended regex). block_if_match() { local pattern="$1" local reason="$2" if echo "$command" | grep -qiE "$pattern"; then echo "{\"decision\": \"block\", \"reason\": \"$reason\"}" exit 2 fi } # Recursive deletion of the root filesystem block_if_match 'rm -rf /' 'Recursive deletion from root is not allowed' # sudo: prevents privilege escalation block_if_match 'sudo ' 'Commands with sudo are not allowed' # World-writable permissions: a common misconfiguration that opens security holes block_if_match 'chmod 777' 'chmod 777 is not allowed: use more restrictive permissions' # Direct disk write: can wipe an entire disk in seconds block_if_match 'dd if=' 'Direct disk writes with dd are not allowed' # Filesystem formatting: permanently destroys data block_if_match 'mkfs' 'Formatting filesystems is not allowed' # Fork bomb: crashes the system by spawning processes until resources are exhausted block_if_match ':\(\)\{' 'Fork bombs are not allowed' # Piping curl or wget output directly into a shell: # executes arbitrary remote code without review block_if_match 'curl.+\|.+bash' 'Piping curl into bash is not allowed' block_if_match 'curl.+\|.+sh' 'Piping curl output into a shell is not allowed' block_if_match 'wget.+\|.+bash' 'Piping wget into bash is not allowed' block_if_match 'wget.+\|.+sh' 'Piping wget output into a shell is not allowed' # Shutdown and reboot: should never be triggered by an automated agent block_if_match '^shutdown' 'Shutdown commands are not allowed' block_if_match '^reboot' 'Reboot commands are not allowed' # Nothing matched: allow the command exit 0