Trivy can break your CI/CD pipeline by failing builds when it finds vulnerabilities.
The core issue is that Trivy, by default, exits with a non-zero status code when it detects vulnerabilities above a configured severity threshold. GitHub Actions, by default, treats any non-zero exit code from a step as a failure, thus halting your pipeline.
Here are the common reasons why Trivy might be failing your builds, and how to fix them:
-
Default Vulnerability Threshold: Trivy’s default configuration is quite strict. It will fail the build if it finds any vulnerabilities of severity
CRITICALorHIGH.- Diagnosis: Run Trivy locally with the
-vflag to see the detailed output and the severities it’s flagging. - Fix: Use the
--severityflag to adjust the threshold. For example, to only fail onCRITICALvulnerabilities:trivy image --severity CRITICAL your-docker-image:tag - Why it works: This explicitly tells Trivy to only consider vulnerabilities of the specified severity for its exit code, allowing lower severities to pass.
- Diagnosis: Run Trivy locally with the
-
Misconfigured
exit-codeFlag: You might have intended to use the--exit-codeflag to control the exit code but got the value wrong or didn’t specify it when you thought you did.- Diagnosis: Review your GitHub Actions workflow YAML file for the exact
trivycommand being executed. Check if--exit-codeis present and what value it’s set to. - Fix: Ensure the
--exit-codeflag is set appropriately for your needs. For instance, to always pass (exit code 0) regardless of findings:
Or, to exit with code 1 fortrivy image --exit-code 0 your-docker-image:tagHIGHandCRITICAL, and 0 otherwise:trivy image --exit-code 1 --severity HIGH,CRITICAL your-docker-image:tag - Why it works: The
--exit-codeflag directly controls the program’s return code. Setting it to0overrides any vulnerability findings that would otherwise cause a failure.
- Diagnosis: Review your GitHub Actions workflow YAML file for the exact
-
Incorrect Target Image or File: Trivy might be scanning the wrong artifact, or a temporary build artifact that contains known, acceptable vulnerabilities.
- Diagnosis: Double-check the
imageorfilesystempath provided to Trivy in your GitHub Actions workflow. Ensure it points to the final, intended artifact. - Fix: Correct the target path. If you’re scanning a Docker image, ensure it’s the one you just built and tagged correctly. If scanning a filesystem, ensure you’re pointing to the deployed application directory.
# Example for scanning a specific built image trivy image --severity CRITICAL my-registry/my-app:latest - Why it works: Trivy can only report on what it’s told to scan. Pointing it to the correct artifact ensures you’re assessing the right components.
- Diagnosis: Double-check the
-
Vulnerability Database Not Updated: Trivy relies on an up-to-date vulnerability database. If the database is stale, it might miss new vulnerabilities or report outdated ones, leading to unexpected failures or false positives.
- Diagnosis: Trivy typically downloads the latest database by default. However, if you’re running Trivy in an air-gapped environment or have configured a custom registry, this might be an issue. Check Trivy’s logs for any warnings about database updates.
- Fix: Ensure Trivy has network access to download the latest vulnerability database. If you’re using a custom registry, verify its configuration. You can also manually update the database before running the scan:
trivy image --download-db-only trivy image --severity CRITICAL your-docker-image:tag - Why it works: An updated database ensures Trivy has the latest information on known exploits, leading to more accurate scanning results.
-
Ignoring Specific Vulnerabilities (False Positives/Accepted Risks): Sometimes, you might have specific CVEs that are known, documented, and accepted risks for your application, or they might be false positives.
- Diagnosis: Identify the specific CVEs Trivy is flagging that you wish to ignore. Trivy’s output will clearly list these.
- Fix: Use the
--ignore-unfixedflag to ignore vulnerabilities that have no fix available, or the--ignore-policyflag with a custom policy file.# Ignore all unfixed vulnerabilities trivy image --ignore-unfixed --severity CRITICAL your-docker-image:tag # Example ignore-policy.rego file content: # package trivy.ignore # deny[msg] { # input.Vulnerability.VulnerabilityID == "CVE-2023-1234" # msg := "Ignoring specific CVE as per policy" # } trivy image --ignore-policy ignore-policy.rego --severity CRITICAL your-docker-image:tag - Why it works: These flags allow you to selectively filter out specific vulnerabilities based on their status (unfixed) or custom rules, preventing them from triggering a build failure.
-
GitHub Actions
continue-on-error: While not a Trivy fix, this is a common workflow-level workaround that can mask underlying issues.- Diagnosis: Look for
continue-on-error: trueon the step that runs Trivy in your.github/workflows/*.ymlfile. - Fix: Remove
continue-on-error: truefrom the Trivy step. Instead, use the appropriate Trivy flags (--severity,--exit-code,--ignore-policy) to manage failures correctly.- name: Scan image with Trivy uses: aquasecurity/trivy-action@master with: image-ref: 'your-docker-image:tag' format: 'table' # Remove this line if present: continue-on-error: true # Configure severity and exit code directly in Trivy command or action inputs # Example: # trivy-flags: '--severity HIGH,CRITICAL --exit-code 1' - Why it works:
continue-on-errorsimply allows the workflow to proceed even if a step fails. By removing it and configuring Trivy correctly, you ensure that the build actually fails when vulnerabilities are found, prompting you to address them.
- Diagnosis: Look for
The next error you’ll likely encounter after fixing these is a misunderstanding of how to integrate Trivy’s results into your broader security posture, such as integrating with a vulnerability management platform or developing automated remediation workflows.