chore(ci): Trivy advisory scan ignores unfixed CVEs (Security-tab noise) (#5234)

The advisory Trivy image scan uploaded every HIGH/CRITICAL into the
Security tab without ignore-unfixed, flooding it with ~150 unfixable
base-image OS CVEs (Debian trixie packages with no upstream patch,
overwhelmingly local-only and not reachable from the proxy request
surface). Operators cannot act on those, so they are pure noise.

Add ignore-unfixed:true to the advisory step so it mirrors the existing
CRITICAL blocking gate and surfaces only actionable, fixable
vulnerabilities. Wire trivyignores to a new repo-root .trivyignore that
documents the accepted-risk policy and is the single auditable home for
the rare fixable CVE we must temporarily accept (none at present).

Takes effect on the next release image build (Trivy only runs on tag
builds, not main pushes); fixed CVEs drop out of the SARIF and GitHub
auto-resolves the corresponding alerts.
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-06-28 12:31:41 -03:00
committed by GitHub
parent 0e55bdabd4
commit bc9d18457d
2 changed files with 33 additions and 0 deletions

View File

@@ -344,6 +344,15 @@ jobs:
# Visibility scan: reports HIGH + CRITICAL into the SARIF (Security tab) but # Visibility scan: reports HIGH + CRITICAL into the SARIF (Security tab) but
# never blocks (exit-code 0). The blocking gate below narrows to CRITICAL. # never blocks (exit-code 0). The blocking gate below narrows to CRITICAL.
#
# ignore-unfixed mirrors the blocking gate: the Security tab must surface only
# ACTIONABLE vulnerabilities — ones with a published fix we can pull by rebuilding
# on a patched base or bumping the dep. Without it the advisory upload floods the
# tab with unfixable base-image OS CVEs (Debian trixie packages with no upstream
# patch yet, overwhelmingly local-only and not reachable from the proxy request
# surface), which is noise an operator cannot act on. trivyignores points at the
# repo-root .trivyignore so accepted-risk fixable CVEs have one auditable home.
# See docs/security/SUPPLY_CHAIN.md.
- name: Trivy image scan (SARIF, advisory) - name: Trivy image scan (SARIF, advisory)
if: needs.prepare.outputs.version != 'main' if: needs.prepare.outputs.version != 'main'
continue-on-error: true continue-on-error: true
@@ -353,6 +362,8 @@ jobs:
format: sarif format: sarif
output: trivy-results.sarif output: trivy-results.sarif
severity: HIGH,CRITICAL severity: HIGH,CRITICAL
ignore-unfixed: true
trivyignores: .trivyignore
exit-code: "0" exit-code: "0"
# BLOCKING gate (v3.8.27 cycle-end): fail the release on a CRITICAL CVE in the # BLOCKING gate (v3.8.27 cycle-end): fail the release on a CRITICAL CVE in the

22
.trivyignore Normal file
View File

@@ -0,0 +1,22 @@
# .trivyignore — accepted-risk suppressions for the container image scan
#
# Policy (see docs/security/SUPPLY_CHAIN.md):
# - The Trivy steps in .github/workflows/docker-publish.yml run with
# `ignore-unfixed: true`, so vulnerabilities WITHOUT a published fix are
# already excluded from both the blocking CRITICAL gate and the advisory
# Security-tab upload. You do NOT need an entry here for an unfixable
# base-image OS CVE — it will not be reported.
# - This file is the single auditable home for the rare case where a *fixable*
# CVE must be temporarily accepted (e.g. the upstream fix is not yet in the
# pinned base tag, or the affected package/binary is provably unreachable
# from the proxy request surface and rebuilding now is not justified).
#
# Format — one CVE id per line, each with a justification comment and, where
# possible, an expiry, e.g.:
# # CVE-XXXX-YYYY — <why accepted>; revisit on next base-image bump (YYYY-MM-DD)
# CVE-XXXX-YYYY
#
# Keep this list SHORT and reviewed every release. Prefer fixing (rebuild on a
# patched base / bump the dep) over suppressing. Stale entries are debt.
#
# (No accepted-risk suppressions at present — ignore-unfixed covers the noise.)