Suppression
Suppression directives exclude specific vulnerability findings from a scanner’s output. The Vulnlog CLI generates scanner-specific suppression files from the Vulnlog file, keeping the triage rationale alongside the suppression rules.
Static and Dynamic Suppression
Vulnlog supports two approaches for managing generated suppression files:
- Static (checked in)
-
The generated suppression files (e.g.,
.trivyignore.yaml,.snyk) are committed to the repository. When the Vulnlog file is edited, the suppression files are regenerated and the updated versions committed. This approach makes suppressions visible in code review and provides a clear history of changes. - Dynamic (generated in CI)
-
The suppression files are generated on the fly in the CI pipeline, just before the SCA scanner runs. They exist only temporarily during the pipeline execution and are not committed to the repository. This approach avoids keeping generated files in the repository and ensures suppressions are always in sync with the Vulnlog file.
Both approaches can be combined — for example, using static suppression for local development and dynamic generation in CI. See CI/CD Integration for pipeline examples using dynamic generation.
Suppression Rules
Four rules decide whether an entry appears in the generated suppression file:
- Resolved findings are never suppressed
-
Once a
resolutionis recorded, the vulnerable dependency is gone and the scanner stops reporting the finding on its own. These entries are excluded regardless of verdict orsuppressblock. If the scanner still reports one, the resolution is incomplete and should be fixed rather than suppressed. - Expired suppressions are always dropped
-
A
suppressblock whoseexpires_atdate has passed is excluded, regardless of verdict. Expiry takes precedence over every other rule, so even anot affectedfinding is removed once itsexpires_atlapses. A finding without asuppressblock has no expiry and stays suppressed. not affectedfindings are always suppressed-
The finding does not impact the release, so it is noise and is suppressed automatically; no
suppressblock is required. The one exception is the expiry rule above: if asuppressblock is present and itsexpires_athas passed, the entry is dropped. - Everything else needs an explicit
suppressblock -
affected,risk acceptable, and not-yet-triaged findings are still a live or unknown risk. Suppressing one is a deliberate decision, so it happens only when the report entry carries asuppressblock.
Multiple Reporters
When multiple scanners report the same vulnerability, each scanner is listed as a separate report entry. Suppression is configured independently per reporter, allowing different suppression strategies per scanner.
- id: CVE-2021-002
releases: [ 8.1.1 ]
packages: [ "pkg:maven/example.org/some-dependency@1.1.2" ]
reports:
- reporter: trivy
at: 2021-03-03
- reporter: snyk
at: 2021-03-03
vuln_ids: [ SNYK-2021-002 ]
verdict: not affected
justification: vulnerable code not present
In this example, both Trivy and Snyk reported the same CVE.
The Snyk report entry includes a vuln_ids field with the scanner-specific identifier, which is used instead of the CVE ID when generating the Snyk suppression file.
Since the verdict is not affected, both reporters are automatically included in suppression output.
Adding a suppress block to only one reporter limits suppression to that specific scanner.
Suppression Identifier Resolution
The CLI determines which identifiers to write into the suppression file using this order:
-
vuln_idsvalues from the report entry for the target reporter type, if present. -
The vulnerability’s
idfield.
aliases are not used for suppression.
Supported Reporters
| Value | Scanner | Default Suppression Path | Suppression Support |
|---|---|---|---|
|
Trivy |
|
Yes |
|
Snyk |
|
Yes |
|
OWASP Dependency Check |
|
Planned |
|
Grype |
|
Planned |
|
Cargo Audit (Rust) |
|
Yes (RUSTSEC IDs only) |
|
Semgrep |
— |
No |
|
npm audit |
— |
No |
|
GitHub Dependabot |
— |
No |
|
Generic / non-scanner source |
— |
No |
For reporters of type other, the source field on report entries is required.