Created
March 24, 2026 15:06
-
-
Save m-waqas88/f796b95edc6bc3351defe56c25177a28 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Claude Code safety hook — blocks dangerous commands | |
| # Runs before every Bash tool call via PreToolUse hook | |
| INPUT=$(cat) | |
| COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""') | |
| block() { | |
| echo "BLOCKED: $1" >&2 | |
| exit 2 | |
| } | |
| # ─── File Destruction ───────────────────────────────────────────────────────── | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)rm\s' && block "rm is not allowed" | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)shred\s' && block "shred is not allowed" | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)truncate\s+-s\s+0' && block "truncating files to zero not allowed" | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)dd\s+if=' && block "dd overwrite not allowed" | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)mv\s+(-f\s|.*-f$)' && block "force move not allowed" | |
| # ─── Shell Script Execution ─────────────────────────────────────────────────── | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)(bash|sh|zsh|source|\.)\s+\S+\.(sh|bash|zsh)' \ | |
| && block "executing shell scripts not allowed" | |
| # ─── Remote Code Execution ──────────────────────────────────────────────────── | |
| echo "$COMMAND" | grep -qE '(curl|wget).*\|\s*(ba)?sh' && block "piping remote content to shell not allowed" | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)eval\s' && block "eval not allowed" | |
| # ─── Git: Destructive / History Rewrite ────────────────────────────────────── | |
| echo "$COMMAND" | grep -qE 'git\s+merge\b' && block "git merge not allowed — merge manually" | |
| echo "$COMMAND" | grep -qE 'git\s+rebase\b' && block "git rebase not allowed" | |
| echo "$COMMAND" | grep -qE 'git\s+reset\s+--hard' && block "git reset --hard not allowed" | |
| echo "$COMMAND" | grep -qE 'git\s+push\s+.*(--force|-f)\b' && block "git force push not allowed" | |
| echo "$COMMAND" | grep -qE 'git\s+push\s+.*--force-with-lease' && block "git push --force-with-lease not allowed" | |
| echo "$COMMAND" | grep -qE 'git\s+clean\s+.*-f' && block "git clean -f not allowed" | |
| echo "$COMMAND" | grep -qE 'git\s+(checkout\s+\.|restore\s+\.)' && block "discarding all local changes not allowed" | |
| echo "$COMMAND" | grep -qE 'git\s+branch\s+.*-D\b' && block "git branch force delete not allowed" | |
| echo "$COMMAND" | grep -qE 'git\s+commit\s+.*--amend' && block "git commit --amend not allowed" | |
| echo "$COMMAND" | grep -qE 'git\s+stash\s+drop' && block "git stash drop not allowed" | |
| # ─── Git: Requires Manual Review ───────────────────────────────────────────── | |
| if echo "$COMMAND" | grep -qE 'git\s+commit\b'; then | |
| # Extract commit message from -m / --message flag (double or single quotes) | |
| MSG=$(echo "$COMMAND" | grep -oE -- '-m\s+"[^"]+"' | sed 's/-m[[:space:]]*"//;s/"$//') | |
| [ -z "$MSG" ] && MSG=$(echo "$COMMAND" | grep -oE -- "-m[[:space:]]+'[^']+'" | sed "s/-m[[:space:]]*'//;s/'$//") | |
| [ -z "$MSG" ] && MSG=$(echo "$COMMAND" | grep -oE -- '--message\s+"[^"]+"' | sed 's/--message[[:space:]]*"//;s/"$//') | |
| [ -z "$MSG" ] && MSG=$(echo "$COMMAND" | grep -oE -- "--message[[:space:]]+'[^']+'" | sed "s/--message[[:space:]]*'//;s/'$//") | |
| [ -z "$MSG" ] && MSG="(no inline -m flag — editor will open)" | |
| jq -n --arg msg "$MSG" --arg cmd "$COMMAND" '{ | |
| hookSpecificOutput: { | |
| hookEventName: "PreToolUse", | |
| permissionDecision: "ask", | |
| permissionDecisionReason: ("Commit message: \"" + $msg + "\"\n\nCommand: " + $cmd) | |
| } | |
| }' | |
| exit 0 | |
| fi | |
| echo "$COMMAND" | grep -qE 'git\s+push\b' && block "git push requires your review — push manually" | |
| # ─── Publishing / Deploying ─────────────────────────────────────────────────── | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)npm\s+publish\b' && block "npm publish not allowed" | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)cargo\s+publish\b' && block "cargo publish not allowed" | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)docker\s+push\b' && block "docker push not allowed" | |
| # ─── Privilege Escalation ───────────────────────────────────────────────────── | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)sudo\s' && block "sudo not allowed" | |
| # ─── System Power Commands ──────────────────────────────────────────────────── | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)(shutdown|reboot|halt)\b' && block "system power commands not allowed" | |
| # ─── Process Killing ────────────────────────────────────────────────────────── | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)kill\s+-9\b' && block "kill -9 not allowed" | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)(killall|pkill)\s' && block "killall/pkill not allowed" | |
| # ─── Permission / Ownership Changes ────────────────────────────────────────── | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)chmod\s+.*-R' && block "recursive chmod not allowed" | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)chown\s+.*-R' && block "recursive chown not allowed" | |
| # ─── Unreviewed Package Installs ───────────────────────────────────────────── | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)npm\s+(install|i)\s+.*-g\b' && block "global npm install not allowed — install manually after review" | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)pip\s+install\b' && block "pip install not allowed — install manually after review" | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)brew\s+install\b' && block "brew install not allowed — install manually after review" | |
| # ─── Shell History & Cron ───────────────────────────────────────────────────── | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)history\s+-c\b' && block "clearing shell history not allowed" | |
| echo "$COMMAND" | grep -qE '(^|\s|;|\||&&)crontab\s+-r\b' && block "crontab -r not allowed" | |
| exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment