The contained runner that drove the 2026-09 security audit, the README review and four rounds of design ideation lived only inside the ignored notebook. It moves to scripts/agent-runner/: the prepare, tools, audit, ideation and teardown scripts, the compose and container files, the allowlist proxy and the prompt templates, with the paths that assumed the notebook fixed and findings written to a caller-named directory. Run outputs, transcripts and the round-specific sheet scripts stay behind. docs/agent-runner.md states the method: the disposable git archive copy and the fail-closed proxy, how a task is shaped, union rather than intersection of findings across models, separate adjudication of every finding against the source, and the evidence a finding must carry.
51 lines
2.6 KiB
Bash
Executable File
51 lines
2.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Deterministic scanner pass. Runs every tool offline inside the auditor
|
|
# container against the disposable copy, writing machine-readable output to
|
|
# $OUT/tools/ for the models to triage (task T08).
|
|
#
|
|
# Evidence for doing this: an LLM adjudicating scanner output cuts semgrep's
|
|
# false-positive rate from ~0.42 to ~0.05 for a ~3% relative recall cost.
|
|
#
|
|
# Usage: OUT=<findings dir> ./run-tools.sh
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")"
|
|
[[ -d .code ]] || { echo "Run ./prepare.sh first." >&2; exit 1; }
|
|
: "${OUT:?set OUT to the directory that receives findings (a run directory of your own, outside this one)}"
|
|
mkdir -p "$OUT"; OUT="$(cd "$OUT" && pwd)"; export OUT
|
|
mkdir -p "$OUT/tools"
|
|
|
|
echo "==> Running scanners (offline) — output to $OUT/tools/"
|
|
docker compose run --rm --no-deps -T auditor bash -c '
|
|
set +e
|
|
mkdir -p /out/tools
|
|
echo "-- gosec"
|
|
gosec -fmt=json -quiet -out=/out/tools/gosec.json ./... 2>/out/tools/gosec.err
|
|
echo "-- govulncheck"
|
|
govulncheck -db=file:///opt/vulndb -format=json ./... \
|
|
>/out/tools/govulncheck.json 2>/out/tools/govulncheck.err
|
|
echo "-- semgrep"
|
|
semgrep --metrics=off --json --quiet \
|
|
--config /opt/semgrep-rules/go \
|
|
--config /opt/semgrep-rules/generic . \
|
|
>/out/tools/semgrep.json 2>/out/tools/semgrep.err
|
|
echo "-- staticcheck"
|
|
staticcheck ./... >/out/tools/staticcheck.txt 2>&1
|
|
echo "-- gitleaks"
|
|
gitleaks detect --no-git --report-format json \
|
|
--report-path /out/tools/gitleaks.json \
|
|
>/out/tools/gitleaks.txt 2>&1
|
|
true
|
|
'
|
|
|
|
echo
|
|
echo "==> Scanner summary"
|
|
cnt() { jq -r "$2" "$OUT/tools/$1" 2>/dev/null || echo "?"; }
|
|
printf " %-14s %s\n" "gosec" "$(cnt gosec.json '.Issues|length') issues ($(cnt gosec.json '[.Issues[]|select(.severity=="HIGH")]|length') high, $(cnt gosec.json '[.Issues[]|select(.severity=="MEDIUM")]|length') medium)"
|
|
# govulncheck emits a JSON stream, not one document, so slurp it.
|
|
printf " %-14s %s\n" "govulncheck" "$(jq -s '[.[]|select(has("finding"))|.finding.osv]|unique|length' "$OUT/tools/govulncheck.json" 2>/dev/null) reachable advisories"
|
|
printf " %-14s %s\n" "semgrep" "$(cnt semgrep.json '.results|length') hits, $(cnt semgrep.json '.errors|length') errors"
|
|
printf " %-14s %s\n" "gitleaks" "$(cnt gitleaks.json 'length') hits"
|
|
printf " %-14s %s\n" "staticcheck" "$(wc -l < "$OUT/tools/staticcheck.txt" 2>/dev/null || echo 0) diagnostics"
|
|
echo
|
|
echo "Tool output is a lead, not a finding. Task T08 triages it."
|