trivy --exit-code: Fail the Build on HIGH/CRITICAL
trivy --exit-code paired with --severity makes the scan fail the pipeline only when matching vulnerabilities are found.
A scan that always exits 0 informs but does not protect. Combining --exit-code with --severity is how you turn Trivy into a gate that blocks merges on serious findings.
What it does
trivy normally exits 0 regardless of findings. --exit-code N makes it exit with N when at least one vulnerability matches the --severity filter, so the CI step fails. The two flags work together: --severity narrows what counts, --exit-code decides the failure code.
Common usage
# fail the job on HIGH or CRITICAL, but still print everything
trivy image --exit-code 0 --severity LOW,MEDIUM myorg/app:ci
trivy image --exit-code 1 --severity HIGH,CRITICAL myorg/app:ci
# one report, gate only on fixable criticals
trivy image --exit-code 1 --severity CRITICAL --ignore-unfixed myorg/app:ciOptions
| Flag | What it does |
|---|---|
| --exit-code <n> | Exit with n when findings match the severity filter |
| --severity <list> | Which severities count toward the exit code |
| --ignore-unfixed | Exclude vulnerabilities with no fix from the gate |
| --exit-on-eol <n> | Also fail when the base OS is end-of-life |
| --ignorefile <file> | Path to a .trivyignore allowlist |
In CI
A common two-step pattern: run once with --exit-code 0 to always print the full table for visibility, then run again with --exit-code 1 --severity HIGH,CRITICAL to gate. Add --ignore-unfixed so the build is not blocked by CVEs you cannot remediate yet.
Common errors in CI
A pipeline that never fails despite known CVEs almost always forgot --exit-code, or set --severity narrower than the findings. A pipeline that always fails on noise has --severity too broad or is missing --ignore-unfixed. Remember the exit code only fires when a finding matches the filter, so the two flags must agree.