## TL;DR

Re-scan locally to see the exact CVEs, then pull a newer patch tag of the same base image - most base-image CVEs are fixed within days upstream. If the image drags in a full distro userland your app never uses, switch to a slimmer variant. Only ignore a CVE via `.trivyignore` after you have verified it is not exploitable in your deployment.

## The error

```text
myapp:pr-123 (debian 12.8)

Total: 21 (HIGH: 14, CRITICAL: 7)
```

(Trivy prints a table of CVEs above the totals, then exits 1 when findings meet the severity threshold.)

## Fix it

1. Reproduce what CI sees. Run `trivy image --severity HIGH,CRITICAL [your-image-tag]` locally.
   Expected: the same CVE table and totals CI reported.
2. Check for a patched base image. Pull the newest patch tag of the same distro (for example the latest `12.x` point release) and re-scan.
   Expected: the totals drop, often to zero - upstream rebuilds pick up distro security fixes quickly.
3. Shrink the attack surface. If your app does not need the full distro userland, switch the Dockerfile to a slimmer variant of the image and re-scan.
   Expected: OS-package CVEs your app never touches disappear from the report.
4. Triage what remains. For each leftover CVE, check whether the vulnerable package is reachable in your deployment. If a CVE has no fix yet and is genuinely not exploitable for you, add its ID (one per line) to a `.trivyignore` file at the repo root with a comment saying why and when to re-check.
   Expected: trivy exits 0 with the ignore file committed alongside the Dockerfile.
5. Update the Dockerfile base tag, rebuild, and re-run CI.
   Expected: the image-scan check goes green.

## Use this when

- Trivy fails the PR with HIGH or CRITICAL totals on the base image
- You see "HIGH severity vulnerabilities in base image" in the scan step
- The image-scan check is red and the CVEs are all in OS packages, not your app code

## Not for this skill when

- The vulnerabilities are in YOUR application dependencies, not the base OS - bump the dependencies instead (see the snyk and osv-scanner skills)
- Trivy fails with a database download error or network timeout - that is transient infra, retry the job
- The scanner is a different tool (grype, docker scout) - same ideas, different flags and ignore files

## Variant phrasings

- trivy HIGH severity vulnerabilities base image
- trivy scan failed exit code 1
- trivyignore how to use
- trivy base image vulnerabilities PR blocked

## Why it happens

Base images ship a full Linux userland, and every CVE in any installed package counts at its rated severity even if your app never executes that binary. CVE feeds also update faster than base image rebuilds, so a fresh scan can flag CVEs that were published after your base tag was cut.

## Edge cases

- Pin the base image by digest for reproducibility, and refresh the digest on a schedule so pins do not go stale
- `.trivyignore` entries without a review date become permanent - always note when to re-check
- Distroless and minimal variants remove shells and debug tooling; keep a debug variant for incidents if your team needs one
- In air-gapped CI the vulnerability DB goes stale and trivy can fail closed - make sure the DB refresh step runs before the scan

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_LlNRv0kMVEUp6zToTJlHZQ
