diff --git a/examples/branch_guard.py b/examples/branch_guard.py new file mode 100644 index 0000000..969d083 --- /dev/null +++ b/examples/branch_guard.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +"""Branch protection using cchooks SDK. + +Blocks push to main/master and force-push on all branches. +Install: Add to PreToolUse hooks matching "Bash" in settings.json. +""" +import re +from cchooks import create_context +from cchooks.contexts import PreToolUseContext + +ctx = create_context() +if isinstance(ctx, PreToolUseContext): + cmd = ctx.tool_input.get("command", "") + + if re.search(r'\bgit\s+push\b.*\b(main|master)\b', cmd, re.I): + ctx.output.block(reason="Direct push to main/master branch") + elif re.search(r'\bgit\s+push\s+.*--force\b', cmd, re.I): + ctx.output.block(reason="Force push overwrites remote history") + elif re.search(r'\bgit\s+push\s+.*-f\b', cmd, re.I): + ctx.output.block(reason="Force push (-f shorthand)") diff --git a/examples/destructive_guard.py b/examples/destructive_guard.py new file mode 100644 index 0000000..1d80032 --- /dev/null +++ b/examples/destructive_guard.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +"""Destructive command guard using cchooks SDK. + +Blocks rm -rf /, git reset --hard, and similar destructive commands. +Install: Add to PreToolUse hooks matching "Bash" in settings.json. + +Born from: https://github.com/anthropics/claude-code/issues/36339 + (User lost entire C:\Users directory to rm -rf via NTFS junctions) +""" +import re +from cchooks import create_context +from cchooks.contexts import PreToolUseContext + +DANGEROUS = [ + re.compile(r'\brm\s+.*-rf\s+(/|~/?\s*$|\.\./)', re.I), + re.compile(r'\bgit\s+reset\s+--hard', re.I), + re.compile(r'\bgit\s+clean\s+-[a-zA-Z]*f', re.I), + re.compile(r'\bchmod\s+(-R\s+)?777\s+/', re.I), + re.compile(r'\bfind\s+/\s+-delete', re.I), + re.compile(r'Remove-Item.*-Recurse.*-Force', re.I), + re.compile(r'--no-preserve-root', re.I), +] + +ctx = create_context() +if isinstance(ctx, PreToolUseContext): + cmd = ctx.tool_input.get("command", "") + if cmd and not cmd.lstrip().startswith(("echo ", "printf ")): + for pattern in DANGEROUS: + if pattern.search(cmd): + ctx.output.block(reason=f"Destructive command: {cmd[:80]}") + break diff --git a/examples/secret_guard.py b/examples/secret_guard.py new file mode 100644 index 0000000..d387add --- /dev/null +++ b/examples/secret_guard.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +"""Secret leak prevention using cchooks SDK. + +Blocks git add .env, credential files, and git add . when .env exists. +Install: Add to PreToolUse hooks matching "Bash" in settings.json. + +Born from: https://github.com/anthropics/claude-code/issues/16561 + (API keys committed via git add .) +""" +import os +import re +from cchooks import create_context +from cchooks.contexts import PreToolUseContext + +ctx = create_context() +if isinstance(ctx, PreToolUseContext): + cmd = ctx.tool_input.get("command", "") + + # Block git add .env* + if re.search(r'\bgit\s+add\s+.*\.env\b', cmd, re.I): + ctx.output.block(reason="Adding .env file to git exposes secrets") + + # Block git add of credential files + elif re.search(r'\bgit\s+add\s+.*(\.pem|\.key|id_rsa|credentials)', cmd, re.I): + ctx.output.block(reason="Adding credential file to git") + + # Warn on git add . / git add -A (may include .env) + elif re.search(r'\bgit\s+add\s+(-A|--all|\.)\s*$', cmd): + if os.path.exists('.env') or os.path.exists('.env.local'): + ctx.output.block(reason="git add all with .env present — use specific files")