`${DIGEST:?}` aborts the script when DIGEST is unset/empty (i.e. when no
upstream checker findings exist). Replace with null-safe `${DIGEST:-}` so
the report-only mode exits cleanly on a clean week.
|
||
|---|---|---|
| .github | ||
| canary | ||
| canary-meta | ||
| checkers | ||
| hooks | ||
| iam | ||
| lib | ||
| skill | ||
| .gitignore | ||
| .security-review-skip | ||
| checker_coordinator.sh | ||
| cross_review.py | ||
| finding.schema.json | ||
| install-hooks.sh | ||
| nightly_sweep.sh | ||
| README.md | ||
| requirements.txt | ||
| review.sh | ||
| ruff.toml | ||
| run_headless.py | ||
| sweep-targets.txt | ||
| test_imports.py | ||
security-review
The Sea Haven security-review gate. One pure-code script (review.sh) is the decision-maker; everything
else (hooks, the interactive skill, the headless runner, the nightly sweep) is a trigger that feeds it.
See memory project-security-review-agent for the full design.
Pieces
review.sh— merges deterministic-scanner findings + agent findings, dedups, applies suppressions (justification required), and makes the block decision (no agent decides). Exit 1 = BLOCK.hooks/pre-commit,hooks/pre-push+install-hooks.sh— fast--scanners-onlygates. Install once globally for every repo, or per-repo (see below).skill/sh-security-review.md— the interactive agentic detector/verifier prompt (Path A, Max-covered).finding.schema.json— the structured finding contract both paths emit.install-hooks.sh --globallinks these into~/.claude/(this repo is the source of truth).run_headless.py— the headless detector fan-out + proof-or-kill verifier (Claude Agent SDK, subscription OAuth). Self-contained: prompts are inline, so the host needs no~/.claudeassets to run it.cross_review.py— the mandatory cross-family GPT-4.1 reviewer CLI (see its section below).nightly_sweep.sh— the retired VM-based two-tier sweep, retained for reference; the automated sweep now runs as Claude Code web cloud routines (see below).
Triggers (one script, many entry points)
- On-demand (primary): run
/sh-security-reviewin a Claude Code session (Max-covered), have it write its schema JSON, thenreview.sh --agent-findings out.json <repo>to gate. Required before pushing payments/auth/IaC/input-handling changes (see the global CLAUDE.md security-review rule). - Pre-commit / pre-push: the global git hooks run deterministic scanners automatically.
- Scheduled: the Claude Code web cloud routines are the unattended backstop (see below).
Installing the hooks
# Global — gate EVERY repo on this machine, and link the skill + schema into ~/.claude:
./install-hooks.sh --global
# Per-repo — for a repo that sets its own core.hooksPath (e.g. husky) and would shadow the global hook:
./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; 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.
--globalalso creates the machine-level suppressions dir (${SH_SECURITY_SUPPRESSIONS_DIR:-~/.config/sea-haven/security-review}): the per-repo file<dir>/<repo-basename>/suppressions.jsonis preferred by the hooks over repo-local.security-review/suppressions.json, andreview.shmerges both when run without--suppressions.
Suppressing a false positive. A written justification is required and is surfaced in the report.
When no --suppressions FILE is passed, review.sh auto-resolves and merges suppressions from
two locations (an explicit --suppressions still overrides both):
- Machine-level (preferred), kept out of repo history:
${SH_SECURITY_SUPPRESSIONS_DIR:-~/.config/sea-haven/security-review}/<repo-basename>/suppressions.json(override the base dir withSH_SECURITY_SUPPRESSIONS_DIR). Keeps a suppression from becoming a permanent in-history "ignore." - Repo-local:
<repo>/.security-review/suppressions.json(tracked; travels with the repo).
Both files' .suppressions[] are concatenated (machine-level first, so it wins any id collision).
This means every entry point — the pre-push hook, the scheduled sweeps, on-demand/CI runs, and the
Open SWE daily-report automation — resolves suppressions identically. Portability note: hosts that
cannot see the Mac's ~/.config (the Open SWE automation, the cloud routines) get only the tracked
repo-local file, so a suppression that must be honored off-Mac has to live repo-local. Fail-safe: if a file is
present but unparseable, nothing is suppressed (the gate blocks).
⚠️ Trust model — automated scanners must target TRUSTED repos only. The repo-local
.security-review/suppressions.jsonis git-tracked, so anyone who can land a commit in a scanned repo can suppress a real finding by committing it alongside the vuln (scanner IDs are deterministic)./sh-security-reviewconfirmed this as a HIGH gate-bypass; it is accepted on the condition that the automated scanners (Open SWE daily report, nightly sweep) only ever scan repos that do not merge untrusted contributions without human review. Seesweep-targets.txt. Relaxing that scoping requires a trust check first (signed / CODEOWNERS-verified repo-local suppressions).
Same JSON either place: {"suppressions":[{"id":"<review.sh finding 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.
CI
The CI here (.github/workflows/) is standard org code-hygiene for this repo's own source (ruff
lint/format + a pytest --collect-only import check, via the Sea-Haven-Industries/.github reusable
workflows) — it is not a security gate over other repos. The gate itself is intentionally not
CI-wired: for a solo dev the git hooks plus the scheduled sweeps are the backstop. The parked CI-backstop
drafts (ci/*.yml, CI-BACKSTOP-NOTES.md) were removed earlier; recover them from history if the team
ever goes multi-dev.
Scanners
review.sh runs whatever is installed and logs the rest with install commands (no silent skips):
semgrep (p/security-audit + p/secrets + p/javascript), gitleaks (git-mode — scans committed
history, respects .gitignore), checkov, cfn-lint, pip-audit, npm audit. Each is normalized into
the finding schema. Install the full set:
pipx install semgrep pip-audit checkov # SAST / vulnerable Python deps / IaC misconfig
brew install gitleaks # hardcoded secrets
# cfn-lint via pip; Node.js provides npm audit
Scheduled execution — Claude Code web cloud routines
The automated sweep runs as Claude Code web cloud routines, both ALARM-only to Slack
#repo-scanner (a clean run posts nothing — see memory feedback_cloudwatch_alarms):
- repo-scanner-nightly-sweep — daily 08:00 ET: the agentic two-tier sweep (deterministic scanners over every repo, plus the bounded agentic detector/verifier rotation).
- repo-checkers-plane1 — daily 07:30 ET: the deterministic
checker_coordinator.sh(the script owns the findings + ALARM decision; the routine relays its output verbatim, never re-judging).
The VM-based Path B sweep is retired (the sweep VM was destroyed); its host artifacts (the
systemd/ units and the DEPLOY-R720.md runbook) are deleted — recover them from git history if
ever needed. nightly_sweep.sh is retained in-repo as the reference implementation of the two-tier
design: GitHub REST API auto-discovery into shallow clean clones, Tier 1 review.sh --scanners-only
over every mirror, Tier 2 bounded agentic run_headless.py round-robin rotation, canary
anti-complacency floor, budget ceilings, and secret redaction. Its optional ENABLE_XMODEL_HOOK=1
critical tiebreak now calls this repo's cross_review.py (default off). Target scoping stays
trusted-repos-only — see sweep-targets.txt.
cross_review.py — mandatory cross-family reviewer
The GPT-4.1 cross-family reviewer CLI, re-homed here from the archived orchestrator repo as a
router-less direct OpenAI SDK call. It is mandatory for IAM/policy and Lambda-handler-signature
changes (per the global instructions), and is the reasoning backend for the sh-plan-review,
sh-security-audit, and sh-build-review gates.
python3 ~/Documents/repositories/seahaven/security-review/cross_review.py "<task>"
Setup: OPENAI_API_KEY in the environment or in the repo-root .env (gitignored — never commit
it); pip install -r requirements.txt provides the openai SDK.