Skip to content

ci: PR-time Trivy image CVE scan (#68)#70

Merged
ilmoniemi merged 3 commits into
mainfrom
feature/68
May 12, 2026
Merged

ci: PR-time Trivy image CVE scan (#68)#70
ilmoniemi merged 3 commits into
mainfrom
feature/68

Conversation

@ilmoniemi
Copy link
Copy Markdown
Contributor

What

Adds an image-scan job to .github/workflows/ci.yml that:

  1. Builds the Dockerfile and tags the image pyrycode-relay:${{ github.sha }}.
  2. Runs aquasecurity/trivy-action@v0.36.0 (pinned by commit SHA) against the just-built image.
  3. Fails the job (exit-code: 1) when a fixable CRITICAL or HIGH CVE is detected (ignore-unfixed: true).
  4. Scans both os and library vuln types — distroless OS packages plus Trivy's Go-binary re-derivation, intentionally overlapping with govulncheck (relay: govulncheck in CI — flag reachable Go vulns at PR time #41).
  5. Declares job-level permissions: contents: read as belt-and-suspenders against future workflow-header widening.

Issue

Closes #68.

Architecture compliance

Implements docs/specs/architecture/68-pr-time-trivy-image-cve-scan-in-ci-yml.md verbatim. New job appended after security (parallel runner), no other files touched — .trivyignore is intentionally not seeded per the spec's allow-list policy.

The Trivy action is pinned by commit SHA (ed142fd0673e97e23eac54620cfb913e5ce36c25, tracking v0.36.0) with a # Tracks: comment mirroring the Dockerfile base-image digest-pin convention from #32. Renovate will surface future bumps as PRs.

Testing

Notes

  • No .trivyignore added — none needed during initial wiring. If a false-positive surfaces in CI, it will be addressed per the policy in the spec (inline-comment-per-suppression with CVE id, reason, revisit date).
  • SARIF / Security-tab publishing intentionally deferred — see spec § Open questions; would require widening permissions to security-events: write.

🤖 Generated with Claude Code

ilmoniemi added 2 commits May 12, 2026 20:10
Adds an `image-scan` job to ci.yml that builds the Dockerfile and runs
Trivy against the just-built image, failing the build on fixable
CRITICAL/HIGH CVEs. Closes the OS-package half of supply-chain CVE
coverage; complements the existing govulncheck source-side scan (#41).

The action is pinned by commit SHA (v0.36.0 →
ed142fd0673e97e23eac54620cfb913e5ce36c25) with a `# Tracks:` comment
mirroring the Dockerfile base-image pin convention (#32). `ignore-unfixed`
keeps unactionable CVEs from blocking PRs; `vuln-type: os,library`
covers both distroless OS packages and Go-binary content. Job-level
`permissions: contents: read` belt-and-suspenders against a future
workflow-header widening.

Refs #68
@ilmoniemi
Copy link
Copy Markdown
Contributor Author

Code Review: #68

Decision: PASS

Findings

None.

Summary

Clean, minimal implementation that matches the spec exactly. One new job (image-scan) appended to ci.yml; no other files touched (correctly — no .trivyignore scaffold per AC).

Verified:

  • AC1 — scan runs after docker build -t pyrycode-relay:${{ github.sha }} .; image tagged with the commit SHA.
  • AC2severity: CRITICAL,HIGH + ignore-unfixed: true + exit-code: '1' fails the job on fixable CRITICAL/HIGH only, per AC.
  • AC3aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 resolves to the commit that annotated tag v0.36.0 dereferences to (verified via git ls-remote refs/tags/v0.36.0^{}). # Tracks: aquasecurity/trivy-action@v0.36.0 comment matches the Dockerfile # Tracks: convention from relay: Dockerfile + base hardening — portable deploy artifact #32.
  • AC4 — job-level permissions: contents: read (belt-and-suspenders against future workflow-level widening, as the spec calls out).
  • AC5 — green run on this PR is the positive verification path. Step log confirms Trivy detected debian 12.13, scanned 4 OS packages + the Go binary, reported 0 fixable CRITICAL/HIGH. Flags echoed in the action's with: block exactly match the spec.

Security-sensitive checks:

  • Spec § Security review present with PASS verdict and per-category findings (trust boundaries, tokens, file ops, subprocess, crypto, network, logs, concurrency, threat-model alignment).
  • Diff has no token/secret surface, no user-controlled subprocess args (${{ github.sha }} is GitHub-provided 40-hex), no write tokens, no repo-tracked file writes.
  • Trivy action pinned by commit SHA (not floating tag) — parity with the Dockerfile base-image digest-pin posture (relay: Dockerfile + base hardening — portable deploy artifact #32).

Nice to have (not blocking): the spec's build image comment included a sentence explaining why docker build is plain (no buildx / no GHA cache layer); the diff trimmed it to one sentence. Either is fine — concise is good.

- New codebase/68.md describing the image-scan job, the fixable-only
  failure policy, action-pin convention, and lessons learned.
- features/docker-image.md: replace the "no image scanning wiring"
  deferral with an evergreen CI image scanning section and link to #68.
- INDEX.md: extend the Docker image one-liner to name the new scan job.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@ilmoniemi ilmoniemi merged commit 2128b97 into main May 12, 2026
3 checks passed
@ilmoniemi ilmoniemi deleted the feature/68 branch May 12, 2026 17:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

relay: PR-time Trivy image CVE scan in ci.yml — fail on fixable CRITICAL/HIGH

1 participant