dotfiles/cursor/hooks/block-destructive-shell.sh
ilia 9dc84bf8f5
All checks were successful
CI / skip-ci-check (pull_request) Successful in 23s
CI / secret-scan (pull_request) Successful in 22s
Add Cursor shell hooks for vault and ansible apply gates
Persist destructive/infra footgun hooks in the repo and teach install.sh
to sync them without clobbering a local hooks.json unless overwritten.
2026-07-30 16:50:56 -04:00

60 lines
1.6 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# Cursor hook: beforeShellExecution
# Purpose: deny obviously destructive commands by default, cursor-wide.
# Note: read stdin before the Python heredoc (heredoc would otherwise consume it).
INPUT="$(cat)"
python3 -c '
import json, re, sys
raw = sys.argv[1]
try:
data = json.loads(raw) if raw.strip() else {}
except Exception:
print(json.dumps({
"permission": "deny",
"user_message": "Blocked: safety hook could not parse shell request input.",
"agent_message": "Hook failed to parse input JSON; failing closed."
}))
raise SystemExit(0)
cmd = (data.get("command") or "").strip()
cmd_l = cmd.lower()
blocked_patterns = [
r"\brm\b.*\s-(?:rf|fr)\b",
r"\brm\b.*\s--no-preserve-root\b",
r"\bmkfs(\.\w+)?\b",
r"\bdd\b\s+if=",
r"\bwipefs\b",
r"\bshred\b",
r"\btruncate\b.*\s-s\s*0\b",
r"\bgit\s+push\b.*\s--force(?:-with-lease)?\b",
r"\bgit\s+reset\b.*\s--hard\b",
r"\bgit\s+clean\b.*\s-(?:ff|fd|xdf)\b",
r"\bterraform\s+destroy\b",
r"\bterraform\s+apply\b(?!.*\s-auto-approve\b)",
r"\bkubectl\s+delete\b",
r"\bansible-playbook\b.*\s--flush-cache\b",
]
blocked_literals = {
"sudo rm -rf /",
"rm -rf /",
}
is_blocked = cmd_l in blocked_literals or any(re.search(p, cmd_l) for p in blocked_patterns)
if is_blocked:
print(json.dumps({
"permission": "deny",
"user_message": "Blocked: potentially destructive command (Cursor safety hook).",
"agent_message": f"Denied by global hook. Command was: {cmd}"
}))
else:
print(json.dumps({"permission": "allow"}))
' "$INPUT"