How do you use Trivy's .trivyignore file and policy-based exceptions?
Quick Answer
The .trivyignore file allows teams to suppress specific CVEs from Trivy scan results by listing vulnerability IDs one per line, optionally with expiration dates and justification comments. Policy-based exceptions extend this further using OPA Rego policies to define conditional suppression rules based on severity, package name, or affected service.
Detailed Answer
Think of the .trivyignore file as an airport security's known traveler list. Certain passengers have been thoroughly vetted and pre-approved, so they bypass the standard screening without triggering an alarm. Without this mechanism, every known frequent flyer would set off the checkpoint every single time, causing delays and desensitizing security staff to real threats. Similarly, .trivyignore prevents known, accepted vulnerabilities from blocking the pipeline, keeping the scan results focused on actionable findings.
The .trivyignore file is a plaintext file placed in the root of your repository that tells Trivy to skip specific vulnerabilities during scanning. Each line contains a CVE identifier such as CVE-2023-44487 or a vulnerability ID from another advisory source like GHSA identifiers. When Trivy encounters a vulnerability whose ID matches an entry in .trivyignore, it silently excludes that finding from the output and does not count it toward the exit code calculation. This means a pipeline configured with --exit-code 1 and --severity CRITICAL will pass even if a CRITICAL vulnerability exists, provided that vulnerability is listed in .trivyignore. Comments can be added using the hash symbol, and best practice demands that every ignored CVE include a comment explaining the business justification, the risk acceptance owner, and an expiration date after which the suppression should be reviewed.
Trivy supports an extended .trivyignore format using YAML-like metadata blocks that provide more granular control. Each entry can include an exp field specifying an expiration date in YYYY-MM-DD format, after which Trivy will stop ignoring the vulnerability and it will reappear in scan results. This is critical for compliance because it prevents indefinite suppression of known risks. For the user-auth-service, you might suppress CVE-2024-21626 with an expiration of 30 days, giving the team a window to plan the upgrade while keeping the pipeline unblocked. When the expiration passes, the vulnerability resurfaces automatically, forcing resolution. Trivy also supports a statement field where teams document who approved the exception, under what conditions, and what compensating controls are in place.
Policy-based exceptions take this concept further by using OPA Rego policies to define conditional suppression rules that apply across the entire organization rather than per-repository. Instead of maintaining individual .trivyignore files in every service repository, a central security team can publish a Rego policy that suppresses certain low-risk vulnerabilities across all scans when specific conditions are met. For example, a policy might suppress vulnerabilities in development-only dependencies that are not present in the final production image, or suppress CVEs that only affect a specific CPU architecture that the organization does not use. These policies are stored in a central repository and referenced during CI scans using the --policy flag or through Trivy's integration with OPA Gatekeeper in Kubernetes environments. The inventory-sync service team, for instance, might have a policy that allows medium-severity findings in test dependencies but enforces strict zero-tolerance for any severity in runtime dependencies.
A critical gotcha with .trivyignore is the temptation to add CVEs without expiration dates, effectively creating a permanent suppression list that grows unchecked over time. Within months, the ignore file can contain dozens of entries that nobody remembers approving, and some may have patches available that the team never revisited. Enforce a mandatory expiration date policy using a CI check that validates the .trivyignore file format and rejects entries without exp fields. Another common mistake is ignoring vulnerabilities at the CVE level when they should be ignored at the package level, or vice versa. A single CVE might affect multiple packages, and ignoring the CVE suppresses all of them, which may not be the intent. Use Trivy's package-specific ignore syntax when you want finer control. Finally, always store .trivyignore in version control alongside the Dockerfile so that exception history is auditable and changes require code review approval from the security team.