Vulnerability Basics
This page is a hands-on intro to scanning container images with Trivy and Grype, reading their output, and wiring severity thresholds into CI so bad images fail the build.
Search across all documentation pages
This page is a hands-on intro to scanning container images with Trivy and Grype, reading their output, and wiring severity thresholds into CI so bad images fail the build.
You build images with Docker, but remember that containerd via the CRI runs the pods on your nodes. Scanning happens against the image artifact, so it protects both worlds equally.
syft SBOM tool.Quick install on Debian/Ubuntu:
# Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin
# Grype
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sudo sh -s -- -b /usr/local/binRun Trivy against any local or remote image reference.
trivy image myapp:1.4.0LOW, MEDIUM, HIGH, CRITICAL.UNKNOWN bucket holds findings with no scored severity yet.Grype gives you a second opinion from a different feed and matcher.
grype myapp:1.4.0FIXED-IN column tells you whether an upgrade path exists.Noise drops sharply when you hide vulnerabilities with no available fix.
trivy image --ignore-unfixed myapp:1.4.0--ignore-unfixed hides CVEs that have no patched version yet.The whole point of CI scanning is a non-zero exit code that stops the pipeline.
trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:1.4.0--exit-code 1 makes Trivy return failure when matching findings exist.--severity HIGH,CRITICAL limits the gate to the severities you block on.0, so the pipeline continues to publish.CRITICAL only, then tighten to HIGH as you clean up.An SBOM is a package inventory you can scan later without the original image.
trivy image --format cyclonedx --output sbom.json myapp:1.4.0trivy sbom sbom.json to re-check against a fresh DB.Catch dependency CVEs before you even build the image.
trivy fs --scanners vuln,secret .trivy fs reads lockfiles like package-lock.json or go.sum.secret scanner also flags committed keys and tokens.Severity comes from CVSS, a 0.0 to 10.0 scale.
CVE-2024-XXXXX openssl 3.0.11 fixed: 3.0.14 CRITICAL (9.8)0.1-3.9 is Low, 4.0-6.9 Medium, 7.0-8.9 High, 9.0-10.0 Critical.Wire the scan into a pipeline so no one can merge a Critical image.
- name: Scan image
uses: aquasecurity/trivy-action@master
with:
image-ref: myapp:${{ github.sha }}
severity: CRITICAL
exit-code: "1"
ignore-unfixed: "true"github.sha ties the scan to the exact commit under test.Sometimes you must accept a CVE briefly while a fix lands upstream.
# .trivyignore.yaml
vulnerabilities:
- id: CVE-2024-12345
expired_at: 2026-08-01
statement: "No upstream fix; tracked in TICKET-482"expired_at makes the waiver self-destruct, so it cannot rot forever.statement records why, which auditors and teammates will ask for.Large legacy images have a backlog. Block regressions, not history.
trivy image --exit-code 1 --severity CRITICAL --ignore-unfixed myapp:1.4.0--ignore-unfixed with a CRITICAL gate blocks only actionable, severe, fixable issues.HIGH for stronger coverage.Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).
Reviewed by Chris St. John·Last updated Jul 16, 2026