chore: accept known vulnerabilities with an expiry

The vulnerability scan failed preflight on a containerd advisory that dev
already carries and that is deferred to a separate dependency update. The
gate now passes only reachable findings listed with an expiry date, fails
on any new one or on an expired acceptance, and warns when an acceptance
is no longer needed.
This commit is contained in:
joshsiv-mulga
2026-10-07 13:59:06 +10:00
parent 84293aecd7
commit 3e3bc5dd0a
4 changed files with 108 additions and 1 deletions
+1 -1
View File
@@ -412,7 +412,7 @@ fix:
govulncheck:
@echo "Running govulncheck..."
$(_Q)scripts/run-gate.sh govulncheck go tool govulncheck ./...
$(_Q)scripts/run-gate.sh govulncheck scripts/govulncheck-gate.sh
@echo " govulncheck ok"
# NilAway — advisory nil-panic analysis. Not in preflight due to false positives
+4
View File
@@ -0,0 +1,4 @@
# Reachable vulnerabilities accepted for a bounded time, read by scripts/govulncheck-gate.sh.
# Format: <OSV-ID> <expiry YYYY-MM-DD> <reason>
# The gate fails once the expiry passes: fix the dependency or renew deliberately.
GO-2026-6597 2026-11-07 containerd v2.4.0 image-pull DoS, fixed in v2.4.1; inherited from dev and deferred to a dependency update outside the package-boundary refactor.
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
# Fails on any reachable vulnerability that is not listed in
# govulncheck-accepted.txt, and on any acceptance whose expiry has passed.
# Each line is "<OSV-ID> <YYYY-MM-DD expiry> <reason>"; '#' starts a comment.
# GOVULNCHECK_JSON substitutes a saved -format json report, for tests.
set -euo pipefail
accepted_file=${GOVULNCHECK_ACCEPTED:-govulncheck-accepted.txt}
today=${GOVULNCHECK_TODAY:-$(date -u +%F)}
if [ -n "${GOVULNCHECK_JSON:-}" ]; then
report=$(cat "$GOVULNCHECK_JSON")
else
report=$(go tool govulncheck -format json ./...)
fi
# A finding whose first trace frame names a function is reachable from our
# code; text mode reports only these, so module- and package-level ones pass.
mapfile -t called < <(printf '%s\n' "$report" | jq -rs \
'[.[] | select(.finding) | .finding | select(.trace[0].function) | .osv] | unique | .[]')
declare -A expiry reason
if [ -f "$accepted_file" ]; then
while read -r id until why; do
[[ -z "$id" || "$id" == \#* ]] && continue
expiry[$id]=$until
reason[$id]=$why
done <"$accepted_file"
fi
fail=0
for id in "${called[@]}"; do
if [ -z "${expiry[$id]:-}" ]; then
echo " $id is reachable and not accepted; run 'go tool govulncheck ./...' for the trace"
fail=1
elif [[ "$today" > "${expiry[$id]}" ]]; then
echo " $id acceptance expired on ${expiry[$id]}: ${reason[$id]}"
fail=1
else
echo " $id accepted until ${expiry[$id]}: ${reason[$id]}"
fi
done
for id in "${!expiry[@]}"; do
if ! printf '%s\n' "${called[@]}" | grep -qx "$id"; then
echo " $id is accepted but no longer reported; remove it from $accepted_file"
fi
done
exit "$fail"
+53
View File
@@ -0,0 +1,53 @@
#!/bin/sh
# Tests the accepted-vulnerability gate against saved reports, so the logic is
# checked without running the scanner.
set -u
here=$(cd "$(dirname "$0")" && pwd)
gate="$here/govulncheck-gate.sh"
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT
cat >"$tmp/accepted.txt" <<'EOF'
# comment
GO-2026-6597 2026-11-07 accepted for the test
EOF
cat >"$tmp/reachable.json" <<'EOF'
{"config":{}}
{"finding":{"osv":"GO-2026-6597","trace":[{"module":"m","package":"p","function":"Pull"}]}}
{"finding":{"osv":"GO-2026-0001","trace":[{"module":"m"}]}}
EOF
cat >"$tmp/new.json" <<'EOF'
{"finding":{"osv":"GO-2026-6597","trace":[{"module":"m","package":"p","function":"Pull"}]}}
{"finding":{"osv":"GO-2026-7777","trace":[{"module":"m","package":"p","function":"F"}]}}
EOF
echo '{"config":{}}' >"$tmp/clean.json"
fails=0
check() {
want=$1 name=$2 report=$3 today=$4 accepted=$5 expect=$6
out=$(GOVULNCHECK_JSON="$tmp/$report" GOVULNCHECK_TODAY=$today GOVULNCHECK_ACCEPTED=$accepted bash "$gate" 2>&1)
rc=$?
if [ "$rc" != "$want" ] || ! printf '%s' "$out" | grep -q "$expect"; then
echo "FAIL [$name] rc=$rc want=$want output: $out"
fails=$((fails + 1))
else
echo "ok [$name]"
fi
}
check 0 "accepted reachable finding passes" reachable.json 2026-10-07 "$tmp/accepted.txt" "GO-2026-6597 accepted until 2026-11-07"
check 0 "expiry day itself still passes" reachable.json 2026-11-07 "$tmp/accepted.txt" "accepted until"
check 1 "expired acceptance fails" reachable.json 2026-11-08 "$tmp/accepted.txt" "acceptance expired on 2026-11-07"
check 1 "new reachable finding fails" new.json 2026-10-07 "$tmp/accepted.txt" "GO-2026-7777 is reachable and not accepted"
out=$(GOVULNCHECK_JSON="$tmp/reachable.json" GOVULNCHECK_TODAY=2026-10-07 GOVULNCHECK_ACCEPTED="$tmp/accepted.txt" bash "$gate" 2>&1)
if printf '%s' "$out" | grep -q "GO-2026-0001"; then
echo "FAIL [module-level finding is not reachable] output: $out"
fails=$((fails + 1))
else
echo "ok [module-level finding is not reachable]"
fi
check 0 "fixed finding warns that acceptance is stale" clean.json 2026-10-07 "$tmp/accepted.txt" "no longer reported"
check 1 "missing acceptance file fails reachable finding" reachable.json 2026-10-07 "$tmp/none" "not accepted"
[ "$fails" -eq 0 ] || exit 1