| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- #!/bin/bash
- # hooks/dangerous-cmd-warn.sh
- # PreToolUse hook - warns before destructive or irreversible commands
- # Matcher: Bash
- #
- # Configuration in .claude/settings.json:
- # {
- # "hooks": {
- # "PreToolUse": [{
- # "matcher": "Bash",
- # "hooks": ["bash hooks/dangerous-cmd-warn.sh $TOOL_INPUT"]
- # }]
- # }
- # }
- #
- # Exit codes:
- # 0 = allow (safe or not matched)
- # 2 = block with message (dangerous command detected)
- INPUT="$1"
- if [[ -z "$INPUT" ]]; then
- exit 0
- fi
- # -------------------------------------------------------------------
- # Dangerous patterns and their risk descriptions
- # -------------------------------------------------------------------
- declare -A PATTERNS
- # Git destructive operations
- PATTERNS["git\s+push\s+.*--force"]="Force push can overwrite remote history and lose others' commits"
- PATTERNS["git\s+push\s+-f\b"]="Force push can overwrite remote history and lose others' commits"
- PATTERNS["git\s+reset\s+--hard"]="Hard reset discards all uncommitted changes permanently"
- PATTERNS["git\s+clean\s+-f"]="git clean -f permanently deletes untracked files"
- PATTERNS["git\s+checkout\s+--\s+\."]="Discards all unstaged changes in working directory"
- PATTERNS["git\s+branch\s+-D"]="Force-deletes a branch even if not fully merged"
- PATTERNS["git\s+stash\s+drop"]="Permanently removes a stash entry"
- PATTERNS["git\s+rebase\s+.*--force"]="Forced rebase can rewrite shared history"
- # File system destructive operations
- PATTERNS["rm\s+-rf\s+/"]="Recursive force delete from root - catastrophic data loss"
- PATTERNS["rm\s+-rf\s+~"]="Recursive force delete of home directory"
- PATTERNS["rm\s+-rf\s+\\."]="Recursive force delete of current directory"
- PATTERNS["rm\s+-rf\s+\*"]="Recursive force delete with glob - likely unintended"
- PATTERNS["rmdir\s+/"]="Attempting to remove root directory"
- PATTERNS["> /dev/sda"]="Direct write to block device - destroys filesystem"
- PATTERNS["mkfs\\."]="Formatting a filesystem destroys all data"
- PATTERNS["dd\s+.*of=/dev/"]="Direct disk write - can destroy data"
- # Database destructive operations
- PATTERNS["DROP\s+DATABASE"]="Drops entire database - all data lost"
- PATTERNS["DROP\s+TABLE"]="Drops table and all its data permanently"
- PATTERNS["DROP\s+SCHEMA"]="Drops schema and all contained objects"
- PATTERNS["TRUNCATE\s+TABLE"]="Removes all rows without logging - cannot rollback"
- PATTERNS["DELETE\s+FROM\s+\w+\s*;"]="DELETE without WHERE clause removes all rows"
- PATTERNS["UPDATE\s+\w+\s+SET\s+.*(?!WHERE)"]="UPDATE without WHERE clause modifies all rows"
- # Process/system operations
- PATTERNS["kill\s+-9\s+1\b"]="Killing PID 1 (init/systemd) crashes the system"
- PATTERNS["killall\s+-9"]="Force-kills all matching processes without cleanup"
- PATTERNS["chmod\s+-R\s+777"]="World-writable recursive permissions - security risk"
- PATTERNS["chown\s+-R\s+.*\s+/"]="Recursive ownership change from root"
- # Container operations
- PATTERNS["docker\s+system\s+prune\s+-a"]="Removes ALL unused Docker data (images, containers, volumes)"
- PATTERNS["docker\s+volume\s+prune"]="Removes all unused Docker volumes (data loss)"
- PATTERNS["kubectl\s+delete\s+namespace"]="Deletes entire Kubernetes namespace and all resources"
- PATTERNS["kubectl\s+delete\s+.*--all"]="Deletes all resources of a type"
- # Package/dependency operations
- PATTERNS["npm\s+cache\s+clean\s+--force"]="Clears entire npm cache"
- PATTERNS["pip\s+install\s+--force-reinstall"]="Force reinstalls all packages"
- # Environment/secrets
- PATTERNS["printenv"]="Prints all environment variables (may contain secrets)"
- PATTERNS["env\s*$"]="Prints all environment variables (may contain secrets)"
- PATTERNS["cat\s+.*\\.env"]="Displaying .env file may expose secrets"
- # -------------------------------------------------------------------
- # Check each pattern
- # -------------------------------------------------------------------
- for pattern in "${!PATTERNS[@]}"; do
- if echo "$INPUT" | grep -qEi "$pattern"; then
- echo "WARNING: Potentially dangerous command detected"
- echo "Pattern: $pattern"
- echo "Risk: ${PATTERNS[$pattern]}"
- echo ""
- echo "The command has been blocked. If you're certain this is safe,"
- echo "ask the user to confirm before proceeding."
- exit 2
- fi
- done
- exit 0
|