PreToolUse write-validation hook
A complete, production-shaped command hook: reads tool input from stdin, denies path traversal and system directories, escalates sensitive files to “ask”, and approves everything else. Note the permissionDecision output schema and exit-code contract.
Parameters
Section titled “Parameters”| Parameter | What to supply |
|---|---|
.tool_input.file_path |
extracted from the JSON Claude Code pipes to stdin |
The artifact
Section titled “The artifact”#!/bin/bash# Example PreToolUse hook for validating Write/Edit operations
set -euo pipefail
# Read input from stdininput=$(cat)
# Extract file path and contentfile_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')
# Validate path existsif [ -z "$file_path" ]; then echo '{"continue": true}' # No path to validate exit 0fi
# Check for path traversalif [[ "$file_path" == *".."* ]]; then echo '{"hookSpecificOutput": {"permissionDecision": "deny"}, "systemMessage": "Path traversal detected in: '"$file_path"'"}' >&2 exit 2fi
# Check for system directoriesif [[ "$file_path" == /etc/* ]] || [[ "$file_path" == /sys/* ]] || [[ "$file_path" == /usr/* ]]; then echo '{"hookSpecificOutput": {"permissionDecision": "deny"}, "systemMessage": "Cannot write to system directory: '"$file_path"'"}' >&2 exit 2fi
# Check for sensitive filesif [[ "$file_path" == *.env ]] || [[ "$file_path" == *secret* ]] || [[ "$file_path" == *credentials* ]]; then echo '{"hookSpecificOutput": {"permissionDecision": "ask"}, "systemMessage": "Writing to potentially sensitive file: '"$file_path"'"}' >&2 exit 2fi
# Approve the operationexit 0