diff --git a/security-review/README.md b/security-review/README.md index dc23536..c4cc214 100644 --- a/security-review/README.md +++ b/security-review/README.md @@ -32,10 +32,21 @@ security-review/install-hooks.sh --global security-review/install-hooks.sh /path/to/repo ``` The global mode sets `git config --global core.hooksPath ~/.config/git/hooks`. Skip a repo with a -`.security-review-skip` file at its root; suppress a specific false positive in the repo's -`.security-review/suppressions.json` (a written justification is required and is surfaced); bypass once -with `git push --no-verify`. Caveat: a repo with its own local `core.hooksPath` overrides the global hook -— install per-repo there. See memory `reference_global_security_review_hook`. +`.security-review-skip` file at its root; bypass once with `git push --no-verify`. Caveat: a repo with +its own local `core.hooksPath` overrides the global hook — install per-repo there. See memory +`reference_global_security_review_hook`. + +**Suppressing a false positive.** A written justification is required and is surfaced in the report. The +hooks resolve a suppressions file in this order: +1. **Machine-level (preferred), kept out of repo history:** + `${SH_SECURITY_SUPPRESSIONS_DIR:-~/.config/sea-haven/security-review}//suppressions.json` + (override the base dir with `SH_SECURITY_SUPPRESSIONS_DIR`). Keeps a suppression from becoming a + permanent in-history "ignore." +2. **Repo-local fallback:** `/.security-review/suppressions.json` (used only if no machine-level file exists). + +Same JSON either place: `{"suppressions":[{"id":"","justification":"…"}]}`. Caveat: +machine-level files are keyed by **repo basename**, so two repos sharing a name collide — fine for the +current single-namespace layout under `~/Documents/repositories`. ## No CI — by design There is **no CI** wiring for this gate. For a solo dev the git hooks + nightly VM sweep are the backstop, diff --git a/security-review/hooks/pre-commit b/security-review/hooks/pre-commit index c28b1f6..268973d 100755 --- a/security-review/hooks/pre-commit +++ b/security-review/hooks/pre-commit @@ -14,6 +14,15 @@ fi # Nothing staged -> nothing to do. git diff --cached --name-only --diff-filter=ACM | grep -q . || exit 0 SUP=() -[ -f "$REPO_ROOT/.security-review/suppressions.json" ] && SUP=(--suppressions "$REPO_ROOT/.security-review/suppressions.json") +# 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 # ${SUP[@]+"${SUP[@]}"} = bash-3.2-safe expansion of a possibly-empty array under set -u. exec bash "$REVIEW_SH" --scanners-only ${SUP[@]+"${SUP[@]}"} "$REPO_ROOT" diff --git a/security-review/hooks/pre-push b/security-review/hooks/pre-push index 74118d8..7ca47df 100755 --- a/security-review/hooks/pre-push +++ b/security-review/hooks/pre-push @@ -10,7 +10,16 @@ REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)" || exit 0 REVIEW_SH="${SH_REVIEW_SH:-$HOME/Documents/repositories/orchestrator/security-review/review.sh}" if [ -f "$REVIEW_SH" ]; then SUP=() - [ -f "$REPO_ROOT/.security-review/suppressions.json" ] && SUP=(--suppressions "$REPO_ROOT/.security-review/suppressions.json") + # 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