Skip to content

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

@ilmoniemi

Description

@ilmoniemi

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

  • .github/workflows/ci.yml gains a scan step that runs after the existing Docker image build, against the just-built image tagged with ${{ github.sha }}.
  • The scan fails the job (exit code 1) when any fixable CVE of severity CRITICAL or HIGH is detected in the image; CVEs without a known fix do not fail the build.
  • The scanner action (e.g. aquasecurity/trivy-action) is pinned to a specific version (commit SHA or version tag) — not floating on @main or @latest.
  • The scan job declares minimum permissions (permissions: contents: read); no write tokens.
  • Running the workflow against a known-good image build succeeds; deliberately introducing a vulnerable base image (e.g. swapping in an outdated tag on a throwaway branch) causes the job to fail with a CVE report visible in the step logs.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    security-sensitiveTouches auth, crypto, or internet-exposed input pathssize:sSmall ticket: <100 lines production code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions