#!/bin/sh # Fast, local shift-left gate: block obvious secrets from being committed. # Runs in seconds, needs no toolchain. Enable with: scripts/install-hooks.ps1 # # Bypass in a genuine emergency with: git commit --no-verify (discouraged). staged=$(git diff --cached --name-only --diff-filter=ACM) [ -z "$staged" ] && exit 0 fail=0 report() { echo " BLOCKED: $1"; fail=1; } for f in $staged; do # Skip the hook scripts themselves: they legitimately contain the patterns # (and literals) they search for, so scanning them would self-block. case "$f" in .githooks/*) continue;; esac # Never commit a real env file (only .env.example is allowed). case "$f" in *.env|.env) report "$f looks like a secrets file (.env is git-ignored for a reason)";; esac # Scan staged content for credential patterns. [ -f "$f" ] || continue content=$(git show ":$f" 2>/dev/null) || continue echo "$content" | grep -Eq 'GITEA_TOKEN[[:space:]]*=[[:space:]]*[A-Za-z0-9]' && \ report "$f contains a GITEA_TOKEN value" echo "$content" | grep -Eq 'PGPASSWORD[[:space:]]*=[[:space:]]*[^ \"$]' && \ report "$f hardcodes PGPASSWORD" echo "$content" | grep -q 'BEGIN .*PRIVATE KEY' && \ report "$f contains a private key" # The known dev DB password must never re-enter the tree (see VAPT FINDING-8). echo "$content" | grep -q 'Did10n@c' && \ report "$f contains the real dev DB password" done if [ "$fail" -ne 0 ]; then echo "" echo "Commit blocked: remove the secret(s) above, or use .env (git-ignored)." exit 1 fi exit 0