diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..b1d485e --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +# Pre-commit secret scan for the hyperguild repo. +# +# task check -> security:gitleaks enforces this in CI, but CI is after the +# push. This catches a staged secret before it ever leaves the machine -- +# the infra#39 rotation pass found exactly this class of leak (a printed +# credential, committed, archived into git) and there was no local gate to +# have caught it. Mirrors infra's own .githooks/pre-commit (infra#326). +# +# Enable once per clone: git config core.hooksPath .githooks +# Bypass if absolutely needed: git commit --no-verify + +set -euo pipefail + +GITLEAKS="$(command -v gitleaks || true)" +if [[ -z "$GITLEAKS" && -x "$(go env GOPATH 2>/dev/null)/bin/gitleaks" ]]; then + GITLEAKS="$(go env GOPATH)/bin/gitleaks" +fi + +if [[ -z "$GITLEAKS" ]]; then + echo "⚠ gitleaks not installed — skipping local secret scan (CI still enforces it)." + echo " Install: go install github.com/zricethezav/gitleaks/v8@latest" + exit 0 +fi + +echo "→ Scanning staged changes for secrets..." +if ! "$GITLEAKS" protect --staged --redact --config .gitleaks.toml >/dev/null 2>&1; then + echo " ✗ gitleaks found a secret in the staged changes." + echo " Review with: gitleaks protect --staged --redact --config .gitleaks.toml -v" + echo " If it is a false positive, allowlist it in .gitleaks.toml or add a" + echo " '# gitleaks:allow' comment. Do NOT --no-verify a real secret." + exit 1 +fi +echo " ✓ no staged secrets"