#!/usr/bin/env python3 """Gemini CLI BeforeTool hook for obviously destructive shell commands.""" import json import re import sys from typing import Any DANGEROUS_PATTERNS = [ (r"\brm\s+-rf\b", "Recursive force deletion is blocked by the document harness."), ( r"\bRemove-Item\b(?=.*\b-Recurse\b|\s-r\b)(?=.*\b-Force\b|\s-f\b)", "PowerShell recursive force deletion is blocked by the document harness.", ), (r"\bgit\s+reset\s+--hard\b", "Hard reset is blocked because it can discard user work."), (r"\bgit\s+push\b.*\s--force(?:-with-lease)?\b", "Force push is blocked by the document harness."), (r"\bDROP\s+TABLE\b", "Destructive database commands are blocked by the document harness."), ] def iter_strings(value: Any): if isinstance(value, str): yield value elif isinstance(value, dict): for key, item in value.items(): yield str(key) yield from iter_strings(item) elif isinstance(value, list): for item in value: yield from iter_strings(item) def emit(payload: dict) -> None: print(json.dumps(payload, ensure_ascii=False)) def main() -> int: raw = sys.stdin.read() try: data = json.loads(raw) if raw.strip() else {} except json.JSONDecodeError: data = {} haystack = raw if data: haystack += "\n" + "\n".join(iter_strings(data.get("tool_input", data))) for pattern, reason in DANGEROUS_PATTERNS: if re.search(pattern, haystack, flags=re.IGNORECASE | re.DOTALL): emit({"decision": "deny", "reason": reason, "suppressOutput": True}) return 0 emit({}) return 0 if __name__ == "__main__": sys.exit(main())