Commit Graph
4 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Opus 5.5 4fa63dd1fb feat(security): keep one vulnerability issue per image and comment its unresolved CVEs
The dry-run mirror scan (run 41286420589) reported 10,179 CVE/image pairs
across 135 red digests; one issue per pair would flood the tracker. The
sync now keeps exactly one open issue per pinned image:

- The body lists every CVE row (id, severity, engine, role, service,
  package, installed, fixed), CRITICAL first, and stops below 60,000
  characters with the number of rows left out and a pointer to the
  vulnerability-findings artifact. On the dry-run data: 135 issues, 8
  capped, the largest body 59,872 characters.
- A further open issue with the same title closes as a duplicate of the
  oldest one.
- When an image's CVE table changed, the issue gets a "Still unresolved"
  comment with the table and an updated body; an unchanged table leaves the
  issue alone, so a daily run does not add 135 identical comments.

Part of #1324

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 17:48:08 +01:00
kevinveenbirkenbachandClaude Opus 5.5 fcf98028fb test(security): let FakeGh hang a verb instead of subclassing it in the test
CodeQL (py/call-to-non-callable, alerts 1073 and 1074 on PR #1326) could not
see the __call__ of the HangingEdit class defined inside the test method and
flagged both gh() calls in sync(). FakeGh now takes the verbs to hang as a
parameter, so the test double stays one module-level class.

Part of #1324

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 13:10:42 +01:00
kevinveenbirkenbachandClaude Opus 5.5 090e3c115d fix(security): keep OSV downloads atomic, bound the issue sync and lint every suppression entry
CodeRabbit review of PR #1326:

- fetch_databases downloads each OSV archive to all.zip.part and replaces
  all.zip only after the transfer completes. An OSError removes the partial
  file and comes back as an `osv <ecosystem>: <error>` line instead of a
  traceback.
- run_gh bounds every gh call with a 120 s timeout. A failed or hung create,
  edit or close becomes a `failed <action>: <error>` line while the other
  issues and the close pass still run, and the command exits 1.
- The suppression lint checks every list item of a suppressions block, so an
  entry that starts with `until:` still needs its `# nocheck: cve <reason>`
  marker.

Part of #1324

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:45:24 +01:00
kevinveenbirkenbachandClaude Opus 5.5 5e5e61d255 feat(ci): scan the mirrored images daily and track their CVEs as issues
The daily mirror workflow gains a scan job after the sync. It runs
make test-security against the GHCR mirror, writes the failing findings per
image and per CVE into the job summary and uploads the report as the
vulnerability-findings artifact.

- One issue per CVE and image, labelled vulnerability, is opened, updated
  while the finding stays and closed once no engine reports it. Issues are
  only closed when the scan reported no error, so an image that failed to
  scan keeps its issues.
- workflow_dispatch and workflow_call take an issues switch; false is a dry
  run that only produces the summary and the artifact. Scheduled runs always
  sync the issues.
- Only the scan job holds issues: write.

Part of #1324

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 02:44:59 +01:00