Skip to content

VEX: Documenting "Not Exploitable" Without Turning Security into a Checkbox

Everyone tells you that when a VEXVulnerability Exploitability eXchangeA security advisory that communicates whether vulnerabilities affect a specific product and why. says “not exploitable,” you can suppress the finding and move on. They’re wrong.

I’ve watched teams do exactly this. A supplier publishes a known_not_affected status, someone marks the CVECommon Vulnerabilities and ExposuresA standardized identifier for a publicly disclosed cybersecurity vulnerability. as resolved, and the finding drops off the dashboard. Three months later, a configuration change reintroduces the exposure. Nobody remembers the original assessment. That’s not security. That’s a checkbox.

A VEX is an attributable statement about a named product. It is not independent proof of what is deployed, configured, exposed, or reachable in your environment — the same gap that makes SBOMs insufficient on their own. The useful outcome is smaller and more reviewable: for one finding, preserve the VEX assertion and its scope, compare it with local evidence, name an owner, and decide whether to retain, investigate, or deprioritize. If a link is missing or contradictory, keep it unknown.

The CSAF VEX profile (Committee Specification Draft 02, 25 February 2026) exists to communicate whether and why a particular product is affected by a vulnerability. CSAFCommon Security Advisory FrameworkAn OASIS standard for machine-readable security advisories, used as one of the formats for publishing VEX statements. VEX supports four product-status values: fixed, known_affected, known_not_affected, and under_investigation. A VEX profile document must include product and vulnerability information plus one of those status groups. unknown exists in the wider CSAF status vocabulary but does not satisfy the VEX profile requirement.

The format makes an assertion auditable. It does not validate the assertion in your environment.

For known_not_affected, CSAF requires an impact statement for every affected product entry, either a machine-readable flag or a human-readable explanation. Preserve the exact explanation rather than reducing it to a yes/no label.

The CISACybersecurity and Infrastructure Security AgencyThe United States federal agency responsible for cybersecurity guidance, vulnerability coordination, and critical infrastructure protection.-hosted VEX status-justification guidance makes the practical point: a VEX status should inform your assessment, not end it. And the absence of a VEX is not evidence that a product is affected. CISA’s issuance guidance notes that issuing VEX information is a business decision for most suppliers.

This is a Kurio Nova operating model — part of the framework from From SBOM to Actionable Signal — synthesized from the sources below. It is not a CSAF requirement, a compliance framework, or an automated suppression rule.

The evidence-to-decision model with the context stage in strong focus. VEX claims inform but do not replace local evidence. The evidence-to-decision model with the context stage in strong focus. VEX claims inform but do not replace local evidence.

The left side of the diagram covers a product-status statement. The middle covers your environment. Neither side proves the other. That separation matters most when a supplier uses a broad product family, your deployment runs a fork or custom build, or a mitigation depends on configuration.

The CSAF specification defines five machine-readable “not affected” justification flags. They are not interchangeable reasons to mark something safe.

Five VEX justification flags: each claim paired with the local evidence required before accepting it. Five VEX justification flags: each claim paired with the local evidence required before accepting it.
JustificationWhat it claims about the named productEvidence to revisit locally
component_not_presentThe affected component is absent.Product/version and artifact inventory; a different build may include it.
vulnerable_code_not_presentThe component is present but the vulnerable code is absent.Exact source/build lineage and product version.
vulnerable_code_not_in_execute_pathThe code is not reachable through execution in the anticipated product state.Configuration, enabled features, reachability method, coverage, and changed use cases.
inline_mitigations_already_existBuilt-in controls prevent adversary leverage.The mitigation’s enabled state, configuration, and any relevant threat assumptions.
vulnerable_code_cannot_be_controlled_by_adversaryThe producer’s anticipated conditions do not let an adversary control the code.Exposure, input paths, identity boundaries, and changed deployment conditions.

Each flag is bound to identified products or product groups in CSAF. A valid product-family statement may still require work to confirm that the exact product and version you run belongs to that scope. A human-readable impact statement can also be valid, so do not reject a VEX because it lacks one of these flags.

When a VEX justification rests on reachability, treat the analysis method’s coverage as a ceiling on your confidence. A study on Java/JVM dependency reachability showed this, but the finding is bounded to that setting, not a universal measure.

Keep the VEX claim separate from deployment evidence

Section titled “Keep the VEX claim separate from deployment evidence”

A VEX establishes who made a product-status assertion, with what version and scope. It does not show which artifact is running right now.

VEX-to-runtime chain: VEX statement, product identity, artifact digest, deployment reference, runtime observation. VEX-to-runtime chain: VEX statement, product identity, artifact digest, deployment reference, runtime observation.

For a containerized product, an OCI descriptor digest is a content identifier that can join to exact bytes. It does not establish the current workload, configuration, exposure, or safety. In Kubernetes, the ContainerStatus API notes that a runtime image identifier can differ from the image reference declared in the Pod specification. Retain both a declared reference and a dated runtime observation where relevant. Building a DevSecOps Evidence Chain walks through how to join these observations into a reviewable record.

I’m not telling you to collect every possible signal before acting. I’m saying: name which signal supports which conclusion — and which question remains open.

FieldExample record
FindingCVE-2024-38816 in payments-gateway
VEX sourceAcme Networks, ACME-SA-2026-07, version 1.2, released 2026-07-28
Product scopeAcme Gateway 4.2.1; local package/version match recorded separately
Status and rationaleknown_not_affected; inline_mitigations_already_exist
Artifact/deploymentOCI image digest recorded; production workload observation dated 2026-08-03
Local contextMitigation configuration captured; external exposure review incomplete
Dispositioninvestigate, not suppression
Owner and review dateService owner; re-review by 2026-08-10
Reopening eventsVEX revision, image/configuration change, new exposure evidence, or conflicting analysis
Evidence linksRaw VEX, product mapping, digest record, deployment observation, configuration review

You should be able to hand this record to someone else and have them reconstruct why you considered the VEX applicable, which assumptions remain open, and what triggers a re-review.

Four scope-matching checks before accepting a VEX: product match, version match, component scope, and deployment context. Four scope-matching checks before accepting a VEX: product match, version match, component scope, and deployment context.
  • The product or version does not match. A justification for a supplier product family is not evidence for a fork, repackaged component, or a different version.
  • The document is unresolved or incomplete. under_investigation, a missing impact explanation, or a missing product scope leaves the decision open.
  • The evidence is stale. CSAF tracking includes identifiers, release dates, version, and revision history. A released version is not modified in place, so a new version can change the decision context.
  • Local conditions contradict the rationale. A mitigation-dependent claim needs review when configuration, exposure, artifact, or deployment changes.
  • Reachability evidence is too narrow. An analysis result without its method, language/runtime scope, and coverage should not carry a broad “not exploitable” conclusion.
  1. Retain the issuer, role, document ID, status, version, release dates, revision history, vulnerability ID, product scope, and exact impact statement.
  2. Match that scope to your product and version; record ambiguity rather than inferring equivalence.
  3. Record artifact identity and a dated deployment observation separately when they matter to applicability.
  4. State local configuration, exposure, and reachability evidence, including method and coverage.
  5. Have an accountable person select and date a local disposition with a review date and explicit reopening events. Missing or contradictory evidence stays as investigate or unknown.

Take the next VEX-backed finding in your queue. Build the review record before you touch its priority or suppression state. If the finding arrived as a critical CVE, Responding to a Critical CVE provides the per-service routing checklist. If someone else cannot reconstruct your reasoning from the raw assertion, local evidence, and reopening conditions alone, the record is not done.

Article series

From SBOM Findings to Defensible Decisions

Explore every resource in this series, whatever its format.

  1. articleWhy Your SBOM Does Not Protect You (and What Is Missing)
  2. articleFrom SBOM to Actionable Signal: Which Vulnerabilities Should You Actually Fix?
  3. guideBuilding a DevSecOps Evidence Chain: SBOM, Provenance, Deployment, and VEX
  4. articleResponding to a Critical CVE Without Triggering a Flood of False Positives
  5. articleVEX: Documenting "Not Exploitable" Without Turning Security into a Checkbox
  6. articleWhat the Cyber Resilience Act Changes for Software Vulnerability Management