#!/usr/bin/env bash # Sea Haven global pre-push security gate — fast deterministic scanners (review.sh --scanners-only). # Installed via install-hooks.sh --global: lays this down at ~/.config/git/hooks/pre-push and sets # git config --global core.hooksPath ~/.config/git/hooks # Skip a repo: add a .security-review-skip file at its root. Bypass once: git push --no-verify. # Deep agentic pass = on-demand /sh-security-review; nightly VM sweep = the backstop. set -uo pipefail REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)" || exit 0 [ -f "$REPO_ROOT/.security-review-skip" ] && exit 0 REVIEW_SH="${SH_REVIEW_SH:-$HOME/Documents/repositories/seahaven/security-review/review.sh}" if [ ! -x "$REVIEW_SH" ]; then echo "security-review: review.sh is missing or not executable at $REVIEW_SH" >&2 echo "Repair: set SH_REVIEW_SH to the scanner path, or reinstall with:" >&2 echo " ${HOME}/Documents/repositories/seahaven/security-review/install-hooks.sh --global" >&2 exit 1 fi SUP=() # Suppressions: prefer a MACHINE-LEVEL file kept out of repo history # (//suppressions.json), else fall back to a repo-local # .security-review/suppressions.json. Keyed by repo basename — adequate for the # current single-namespace layout under ~/Documents/repositories. MACHINE_SUP="${SH_SECURITY_SUPPRESSIONS_DIR:-$HOME/.config/sea-haven/security-review}/$(basename "$REPO_ROOT")/suppressions.json" if [ -f "$MACHINE_SUP" ]; then SUP=(--suppressions "$MACHINE_SUP") elif [ -f "$REPO_ROOT/.security-review/suppressions.json" ]; then SUP=(--suppressions "$REPO_ROOT/.security-review/suppressions.json") fi echo "security-review: scanning $REPO_ROOT (scanners-only) before push..." >&2 # ${SUP[@]+"${SUP[@]}"} = bash-3.2-safe expansion of a possibly-empty array under set -u. if ! bash "$REVIEW_SH" --scanners-only ${SUP[@]+"${SUP[@]}"} "$REPO_ROOT"; then echo "security-review: BLOCKED (confirmed crit/high). Fix it, suppress with justification, or 'git push --no-verify' to override." >&2 exit 1 fi # Don't silently disable a repo-local pre-push hook: chain to it if present. LOCAL_HOOK="$REPO_ROOT/.git/hooks/pre-push" [ -x "$LOCAL_HOOK" ] && exec "$LOCAL_HOOK" "$@" exit 0