anchore/grype
VEX processing
Active contributors: Alex Goodman, Will Murphy
Purpose
VEX (Vulnerability Exploitability eXchange) lets a vendor or operator declare whether a vulnerability actually applies to their product. Grype consumes VEX documents to either filter out matches that the vendor has marked as not applicable, or augment matches when the vendor has marked something as affected that Grype would otherwise miss.
Grype supports two VEX formats:
- OpenVEX —
grype/vex/openvex/ - CSAF VEX —
grype/vex/csaf/(usesgocsaf/csaf/v3)
Directory layout
grype/vex/
├── processor.go # top-level Processor and dispatch
├── csaf/ # CSAF implementation
├── openvex/ # OpenVEX implementation
├── status/ # canonical VEX status enum
└── testdata/ # example documentsProcessor
grype/vex/processor.go::Processor is the public entry. Construction:
p, err := vex.NewProcessor(vex.ProcessorOptions{
Documents: opts.VexDocuments,
IgnoreRules: opts.Ignore,
})The constructor sniffs the first document to decide whether to instantiate the OpenVEX or CSAF implementation. Both implement vexProcessorImplementation:
type vexProcessorImplementation interface {
ReadVexDocuments(docs []string) (any, error)
FilterMatches(any, []match.IgnoreRule, *pkg.Context, *match.Matches, []match.IgnoredMatch) (*match.Matches, []match.IgnoredMatch, error)
AugmentMatches(any, []match.IgnoreRule, *pkg.Context, *match.Matches, []match.IgnoredMatch) (*match.Matches, []match.IgnoredMatch, error)
}Where it runs
Processor.ApplyVEX is invoked from grype/vulnerability_matcher.go::findVEXMatches, which runs after the DB matchers and after user-provided ignore rules. The flow:
ReadVexDocumentsparses every passed document into the implementation's native shape.FilterMatcheswalks the current matches and moves any with statusnot_affectedorfixedinto the ignored set.AugmentMatcheswalks the VEX statements with statusaffectedand adds any vulnerability the scanner would otherwise miss.- The diff is published to the progress monitor so the UI can show new VEX-driven additions and suppressions.
VEX statuses
grype/vex/status/ defines the canonical enum:
| Status | Effect |
|---|---|
not_affected |
Filter the match into the ignored set (with reason from VEX). |
fixed |
Filter the match into the ignored set. |
affected |
Augment matches if the scanner missed it; otherwise leave alone. |
under_investigation |
Pass through; surfaced in JSON output. |
VEX-aware ignore rules
Users can layer VEX-status-based ignore rules:
ignore:
- vex-status: not_affected
- vex-status: fixedvulnerability_matcher.go automatically appends these when the user passes --ignore-vex-fixed or --ignore-vex-not-affected. The corresponding IgnoreRule.VexStatus field is honored by extractVexRules in processor.go.
CSAF specifics
CSAF documents are JSON files with a different schema from OpenVEX. The CSAF implementation walks vulnerabilities[].product_status and matches product references against the package context. It uses Intevation/gval for JSONPath-like expressions where required.
OpenVEX specifics
OpenVEX is much smaller than CSAF — each document is a flat array of statements with vulnerability, products, status, and (optionally) justification/impact_statement. The OpenVEX implementation uses openvex/go-vex for parsing.
Reasoning surfaces in output
When a match is moved to the ignored set by VEX, the applied IgnoreRule.Reason carries "vex" and the JSON output's appliedIgnoreRules array reflects it. --show-suppressed reveals these matches alongside their VEX-derived reasons.
Key abstractions
| Symbol | Where | Description |
|---|---|---|
vex.Processor |
grype/vex/processor.go |
Public entry. |
vex.ProcessorOptions |
same | Documents + IgnoreRules. |
vex.NewProcessor |
same | Sniffs first doc and picks an implementation. |
status.* |
grype/vex/status/ |
Canonical status enum. |
Key source files
| File | Purpose |
|---|---|
grype/vex/processor.go |
Top-level dispatch. |
grype/vex/openvex/ |
OpenVEX implementation. |
grype/vex/csaf/ |
CSAF implementation. |
grype/vulnerability_matcher.go (findVEXMatches) |
Pipeline integration. |
Entry points for modification
- New VEX format — add a sibling under
grype/vex/, implementvexProcessorImplementation, and extendgetVexImplementationto detect it. - New status semantics — extend
status/and updateFilterMatches/AugmentMatchesin both implementations.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.