User Story
As a relay maintainer, I want CI to scan the freshly-built container image for known CVEs at PR time so that fixable critical/high vulnerabilities in base-image system libraries are caught before merge, not after deploy.
Context
The Dockerfile shipped in #32 introduces a container image into the supply chain. Base-image system libraries accumulate CVEs over time even with pinned-by-digest references. Without PR-time scanning, a known-fixed critical vulnerability can sit in the deployed image until someone notices.
This is the runtime-image half of CVE scanning. The Go-source-side complement (reachable Go vulns via govulncheck) is #41. Both layers cover different artifacts: govulncheck audits Go code + reachable call paths; image scanning audits the base-image system libraries.
docs/threat-model.md § Supply chain — Go dependencies covers the broader posture.
The companion periodic re-scan (which catches CVEs disclosed against dependencies that have not changed since the last PR) is split out to a follow-up ticket and depends on this ticket landing first.
Split from #40.
Acceptance Criteria
Technical Notes
- Grype is an acceptable alternative if Trivy proves operationally noisy; the workflow shape is the same. The architect chooses based on the current state of upstream tooling.
- The action version pin can be tracked by Dependabot/Renovate (already enabled) so updates surface as PRs.
- The image must already be built and locally tagged (or pushed) before the scan step — keep the scan immediately after the build step so it operates on the same artifact the PR would publish.
- Allow-list policy (only if needed): a
.trivyignore (or equivalent) is added only if at least one false-positive or unactionable CVE is encountered during initial wiring — do not check in an empty allow-list scaffold. If introduced, each suppression line must carry an inline comment stating the CVE id, the reason for suppression, and a revisit date.
Size Estimate
S
User Story
As a relay maintainer, I want CI to scan the freshly-built container image for known CVEs at PR time so that fixable critical/high vulnerabilities in base-image system libraries are caught before merge, not after deploy.
Context
The Dockerfile shipped in #32 introduces a container image into the supply chain. Base-image system libraries accumulate CVEs over time even with pinned-by-digest references. Without PR-time scanning, a known-fixed critical vulnerability can sit in the deployed image until someone notices.
This is the runtime-image half of CVE scanning. The Go-source-side complement (reachable Go vulns via
govulncheck) is #41. Both layers cover different artifacts:govulncheckaudits Go code + reachable call paths; image scanning audits the base-image system libraries.docs/threat-model.md§ Supply chain — Go dependencies covers the broader posture.The companion periodic re-scan (which catches CVEs disclosed against dependencies that have not changed since the last PR) is split out to a follow-up ticket and depends on this ticket landing first.
Split from #40.
Acceptance Criteria
.github/workflows/ci.ymlgains a scan step that runs after the existing Docker image build, against the just-built image tagged with${{ github.sha }}.CRITICALorHIGHis detected in the image; CVEs without a known fix do not fail the build.aquasecurity/trivy-action) is pinned to a specific version (commit SHA or version tag) — not floating on@mainor@latest.permissions: contents: read); no write tokens.Technical Notes
.trivyignore(or equivalent) is added only if at least one false-positive or unactionable CVE is encountered during initial wiring — do not check in an empty allow-list scaffold. If introduced, each suppression line must carry an inline comment stating the CVE id, the reason for suppression, and a revisit date.Size Estimate
S