ci: hard-fail PR and release scans on unacknowledged HIGH/CRITICAL CVEs (#484)

* ci: hard-fail PR and release scans on unacknowledged HIGH/CRITICAL CVEs

Make Trivy a real gate instead of an advisory signal:

- PR CI (docker-validate) no longer uses `continue-on-error: true` on the
  Trivy step, so any HIGH/CRITICAL finding not in `.trivyignore` fails the PR.
- The release pipeline (docker-publish.yml) now builds an amd64-only scan
  image into the local daemon before the multi-arch push-build, re-runs
  Trivy against that exact artifact, and only proceeds to the push if the
  scan passes. This closes the gap where a CVE landed between PR merge and
  release-time rebuild.
- New `.trivyignore` at repo root is the single source of truth for
  acknowledged CVEs across both workflows; it starts empty so the first CI
  run surfaces the full list, which we then populate with justifications.

* ci: populate .trivyignore with initial HIGH/CRITICAL acknowledgements

First CI run on the hard-fail Trivy policy surfaced 7 unacknowledged
findings. Each has been reviewed and justified inline:

- 6 CVEs in the statically-linked Go modules inside docker-compose v5.1.1
  (github.com/docker/docker, buildkit, otel/sdk x2, grpc). These are
  transitively bundled and cannot be bumped without an upstream Compose
  rebuild. The grpc CVE is already explicitly acknowledged in the
  Dockerfile rationale block at Dockerfile:108-111.
- 1 CVE in picomatch 4.0.3 bundled inside the npm CLI that ships with
  node:22-alpine. npm is only invoked at build time against our own
  package.json, so the ReDoS vector is not reachable.

Every entry has a revisit trigger (next Compose release or next Alpine
node bump).
This commit is contained in:
Anso
2026-04-10 14:01:02 -04:00
committed by GitHub
parent 3b12f2678f
commit fdb476a84a
3 changed files with 123 additions and 3 deletions
+87
View File
@@ -0,0 +1,87 @@
# Trivy ignore list
#
# Every entry in this file is a known HIGH or CRITICAL CVE that we have
# consciously accepted risk on and decided not to block CI over. Format:
#
# CVE-YYYY-NNNNN
# # Justification: why we're accepting this risk, and a link or note about
# # when to revisit (e.g. "blocked on upstream base image update, revisit
# # when alpine/node:22 ships a fix").
#
# Rules:
# - Every CVE MUST have a justification comment directly above it.
# - If there is no justification, the CVE is not ignored - add it here only
# after a human review and a decision to accept the risk.
# - Review this file on every release; remove entries whose upstream fix has
# landed.
#
# Picked up automatically by aquasecurity/trivy-action from the repo root
# working directory. Both the pre-push PR scan (.github/workflows/ci.yml) and
# the release-time re-scan (.github/workflows/docker-publish.yml) honor it.
# ---------------------------------------------------------------------------
# Bundled inside /usr/local/lib/docker/cli-plugins/docker-compose (v5.1.1)
# ---------------------------------------------------------------------------
# Compose v5.1.1 is the latest upstream release and is already pinned in
# Dockerfile:113 to get us off the v2.40.3 grpc 1.74.2 / x/crypto 0.38.0 CVE
# set. It statically links older copies of github.com/docker/docker,
# buildkit, otel, and grpc. We cannot bump these transitively without
# waiting for a new upstream Compose release. Revisit this block on every
# Compose release; remove entries as upstream rebuilds ship the fixes.
# See the rationale block at Dockerfile:96-111.
# Justification: github.com/docker/docker v28.5.2 statically bundled in
# compose v5.1.1. Moby authz bypass applies to a Docker daemon, not to the
# compose CLI plugin; compose never runs as a daemon. Revisit on next
# Compose upstream release.
CVE-2026-34040
# Justification: github.com/moby/buildkit v0.27.1 statically bundled in
# compose v5.1.1. BuildKit arbitrary file write via untrusted frontend is
# exploited at buildkit build time with attacker-controlled frontends; our
# compose invocations only call up/down/ps against local user-authored
# compose files, never as a build frontend. Revisit on next Compose upstream
# release.
CVE-2026-33747
# Justification: github.com/moby/buildkit v0.27.1 statically bundled in
# compose v5.1.1. Same exposure profile as CVE-2026-33747 (Git URL fragment
# subdir exploitation requires invoking buildkit on untrusted repo URLs,
# which compose does not do in our flow). Revisit on next Compose upstream
# release.
CVE-2026-33748
# Justification: go.opentelemetry.io/otel/sdk v1.38.0 statically bundled in
# compose v5.1.1. PATH hijacking requires the attacker to control the
# process PATH before compose starts; our container starts compose from a
# fixed PATH with only /usr/local/bin and /usr/bin on it, both owned by
# root. Revisit on next Compose upstream release.
CVE-2026-24051
# Justification: go.opentelemetry.io/otel/sdk v1.38.0 statically bundled in
# compose v5.1.1. BSD kenv PATH hijacking only applies on BSD systems; we
# ship linux/amd64 and linux/arm64. Not applicable in our runtime. Revisit
# on next Compose upstream release.
CVE-2026-39883
# Justification: google.golang.org/grpc v1.78.0 statically bundled in
# compose v5.1.1 AND in Docker CLI v29.3.1. Already explicitly acknowledged
# in the Dockerfile rationale block at Dockerfile:108-111 as unpatched,
# waiting on a new Docker CLI or Compose release that ships grpc >= 1.79.3.
# Exploit requires an attacker-controlled HTTP/2 peer talking to a gRPC
# server; compose and the docker CLI only act as gRPC clients against the
# local unix socket, not as servers.
CVE-2026-33186
# ---------------------------------------------------------------------------
# Bundled inside /usr/local/lib/node_modules/npm/ (node:22-alpine base image)
# ---------------------------------------------------------------------------
# Justification: picomatch 4.0.3 is shipped inside the npm CLI that comes
# bundled with the upstream node:22-alpine base image. We do not run npm at
# container runtime against user-controlled input; npm is only invoked at
# build time against our own package.json files. The ReDoS requires an
# attacker-authored extglob pattern, which is not reachable from any
# runtime code path. Revisit when a future node:22-alpine base image ships
# a newer npm that bundles picomatch >= 4.0.4.
CVE-2026-33671