Safeguard
Product•

VEX and CSAF in Safeguard: Telling Customers a CVE Does Not Affect You

Safeguard ingests CSAF 2.0, CycloneDX VEX and OpenVEX (GA) so findings show what does not affect you. Here is how to consume and share VEX you can defend.

Safeguard Security Team
39 min read

You can upload a supplier's CSAF 2.0 advisory or VEX file (CycloneDX VEX, OpenVEX or the CSAF VEX profile) through Integrations in Safeguard, tie it to a project name and version, and use those statements to mark vulnerabilities as not affected and cut false positives. CSAF and VEX upload is GA. To tell your own customers that a CVE does not affect them, you record the evidence in a project's Mitigations tab, write a VEX statement with a justification you can defend, and share it next to the version-scoped SBOM it refers to through Portal (GA) or a Trust Center (early access). Safeguard does not write or sign that claim for you; the judgement stays with your team.

Key takeaways

  • VEX is a claim, not a scan result. It states whether a product is affected, with one of four statuses; "not affected" needs a justification or an impact statement.
  • CSAF and VEX upload (GA) accepts four formats as .json: CSAF 2.0, CycloneDX VEX, OpenVEX and the CSAF VEX profile. The upload is validated automatically and attached to a project name and version.
  • Vulnerability management (GA) and the project Mitigations tab let you record why a finding does not apply, who approved it, the evidence, the scope (this version or all versions) and an expiry date. Active mitigations stop a finding from failing a gate; expired ones do not.
  • Reachability analysis (GA) gives you evidence for a "vulnerable code not in execute path" justification. Safeguard's docs mark static reachability for Ruby and PHP, and both static and dynamic reachability for Swift and Objective-C, as Preview. An "Unknown" result is never grounds for "not affected".
  • Portal (GA), meaning the SBOM publish and share product here, not the free entry tier, shares the version-specific SBOM your VEX statements point at, with expiring links, NDA gates and access tracking.
  • Trust Center (early access) can list documents for customers with Public or Restricted visibility and shows each file's size and SHA-256.
  • Compliance and GRC suite (GA) includes CycloneDX VEX and VEX Readiness frameworks that check the SBOM fields VEX matching depends on.
  • What you still own: the analysis behind every "not affected" statement, the decision to trust a supplier's VEX, signing and publishing your own advisories, and keeping statements current.

Why the "are you affected?" email keeps arriving

Every time a widely used library gets a serious CVE, two queues fill up. Your security team asks whether your products ship the vulnerable component, and customers who scanned the SBOM you gave them ask the same about your product. Both want one answer: does this vulnerability affect this version of this product?

An SBOM alone cannot answer that. It says a component is present, and a scanner will report every CVE for that component and version, whether or not the vulnerable function is ever called or compiled in. CISA's guidance on when to issue VEX describes this exact pattern: when an upstream component vulnerability is disclosed, users assume that presence means risk, contact the supplier directly, and put a burden on the supplier's support and security teams. Issuing VEX information, CISA says, can reduce those support calls.

The same problem runs the other way. Your scanner flags CVEs in the components your suppliers ship you, and without a machine-readable statement from them your team re-triages work the supplier has probably already done, with less context.

Regulation is turning this into an expectation. The EU Cyber Resilience Act and section 524B of the US Federal Food, Drug, and Cosmetic Act both require SBOMs and vulnerability handling, covered below. Neither names VEX, but both describe the job VEX was designed to do.

What are VEX and CSAF?

VEX (Vulnerability Exploitability eXchange) is a way to state the status of a product with respect to a specific vulnerability. CISA's use case document from April 2022 calls VEX "a form of a security advisory" and points out two improvements over traditional advisories: VEX is machine readable, and it is designed to work with SBOM data. VEX is a concept with minimum data elements; it is implemented in several formats.

CSAF (Common Security Advisory Framework) is an OASIS standard for machine-readable security advisories. Version 2.0 became an OASIS Standard on 18 November 2022. CSAF covers more than VEX: it defines several document profiles, including security advisories and a dedicated VEX profile. So "CSAF VEX" is one of the formats a VEX statement can take, and a CSAF security advisory from a vendor can carry the same product status information in a broader document.

If you want the longer history of how the two fit together, our earlier posts on how VEX works in Safeguard and the CSAF 2.0 guide to machine-readable advisories go deeper on the formats themselves.

What CISA's minimum requirements for VEX define

CISA published "Minimum Requirements for Vulnerability Exploitability eXchange (VEX)" in April 2023. It defines the data elements independently of any format, uses RFC 2119 language (MUST, SHOULD, MAY), and labels its own requirements as version 1.0.0. The parts that matter most in practice:

Document metadata. A VEX document MUST contain at least one statement, one document identifier, a document version incremented on every change, an identified author (an individual or organisation, not a tool) and first issued and last updated timestamps in a format such as RFC 3339. The author's identity SHOULD be cryptographically tied to a signature on the document.

Statements. Each statement MUST convey a single status for a single vulnerability identifier, applied to one or more products, with its own identifier, version and timestamps.

Products and vulnerabilities. Product identifiers SHOULD reference SBOM identifiers and MAY be versions, ranges, hashes or sets. A subcomponent can be affected while the product containing it is not. Each statement MUST name one vulnerability, ideally by CVE, and include or reference its description.

No default status. This is the line people miss. CISA states that VEX does not specify, assume or imply any default status that is not explicitly provided. If a supplier's VEX says nothing about a CVE, that silence tells you nothing.

What the OASIS CSAF 2.0 standard defines

CSAF 2.0 is a full JSON schema plus conformance rules, so it is more prescriptive than CISA's format-neutral list. Section 4.5, "Profile 5: VEX", says a document claiming the VEX profile must:

  • set /document/category to csaf_vex;
  • include a product_tree listing every product referenced later in the document;
  • include vulnerabilities, and for each one at least one of the fixed, known_affected, known_not_affected or under_investigation product status lists;
  • identify the vulnerability through cve, ids or notes;
  • give every product in known_not_affected an impact statement, either as a machine-readable flag in flags or as a human-readable threats entry with category impact;
  • give every product in known_affected a product-specific action statement in remediations (the categories no_fix_planned and none_available are allowed).

The profile tests in section 6.1.27 add that a csaf_vex document must have a product_tree (test 6.1.27.4) and that every vulnerability item must have notes (test 6.1.27.5).

CSAF defines eight product status lists in total; the extras, such as last_affected and first_fixed, let a vendor describe release trains.

Section 7 covers distribution, with requirements such as a provider-metadata.json file (requirement 7) at a well-known URL (requirement 9), TLS (requirement 3) and OpenPGP signatures (requirement 19). OASIS also hosts drafts of CSAF 2.1; Safeguard's docs list CSAF 2.0.

Which VEX statuses exist, and which justifications are allowed for "not affected"?

CISA's minimum requirements define four statuses:

  • Not affected (not_affected): no remediation or mitigation is required; the vulnerability does not affect the listed products.
  • Affected (affected): the author recommends actions to remediate or mitigate. An affected statement MUST include an action statement.
  • Fixed (fixed): the listed products contain fixes for the vulnerability.
  • Under investigation (under_investigation): the author has not yet reached a final status, and the status is expected to change.

For "not affected", a statement SHOULD carry a justification, and if it does not, it MUST carry an impact statement explaining why. CISA's June 2022 status justification document and the April 2023 minimum requirements list five justifications:

JustificationWhat it asserts (CISA's definition, paraphrased)
component_not_presentThe vulnerable subcomponent is not included in the product.
vulnerable_code_not_presentThe subcomponent is included, but the vulnerable code is not, typically because of how it was configured or built.
vulnerable_code_not_in_execute_pathThe vulnerable code is included but the product does not call or otherwise use it.
vulnerable_code_cannot_be_controlled_by_adversaryThe vulnerable code is present and used, but an attacker cannot control it to exploit the vulnerability.
inline_mitigations_already_existBuilt-in protections, which the attacker cannot subvert and the user cannot disable, prevent exploitation based on known attack vectors.

CSAF 2.0 uses the same five values as the enum for flags[].label, and OpenVEX v0.2.0 uses them too. CSAF's wording for vulnerable_code_not_in_execute_path sets a high bar: the code is "not reachable through the execution of the code, including non-anticipated states of the product." Keep that phrase in mind when we reach reachability below.

The CISA justification document also makes a point that should shape your whole program: status justifications are assertions made by the author, and the consumer can choose to accept them or not. CISA's use case document adds that a VEX status is meant to inform the consumer's decision, not to end the discussion.

How the four formats express the same statuses

CISA statusCSAF 2.0 product statusCycloneDX analysis.stateOpenVEX status
Not affectedknown_not_affectednot_affectednot_affected
Affectedknown_affectedexploitableaffected
Fixedfixed (and first_fixed)resolved (or resolved_with_pedigree)fixed
Under investigationunder_investigationin_triageunder_investigation

CycloneDX adds one state the others lack: false_positive, meaning the vulnerability was wrongly associated with the component in the first place. That is different from not_affected, where the association is correct but the product is not exploitable.

CycloneDX uses its own justification vocabulary. As of the 1.6 schema, the values are code_not_present, code_not_reachable, requires_configuration, requires_dependency, requires_environment, protected_by_compiler, protected_at_runtime, protected_at_perimeter and protected_by_mitigating_control. None of the sources we read publishes an official mapping to CISA's list, so do not translate mechanically. In particular, protected_at_perimeter and protected_by_mitigating_control describe controls outside the product, which CISA's inline_mitigations_already_exist excludes.

CSAF VEX, CycloneDX VEX and OpenVEX: when does each fit?

All three are JSON, all three are accepted by Safeguard's upload, and all three can carry a defensible "not affected" statement. The choice depends mostly on who reads the document and what else you already publish.

FormatShapeFits best whenWatch for
CSAF 2.0 VEX profileA full advisory document with document, product_tree and vulnerabilities; product status lists per vulnerabilityYou already publish security advisories, your customers run advisory aggregation, or you sell into sectors that consume CSAF feedsThe most fields to get right; product_tree, per-vulnerability notes and an impact statement for every not-affected product are required by the profile
CycloneDX VEXA vulnerabilities array with analysis (state, justification, response, detail, timestamps) and affects references to components, inside a CycloneDX BOM or a standalone BOM that links to oneYour SBOMs are already CycloneDX and you want VEX that references the exact bom-ref entriesIts justification vocabulary differs from CISA's; affects versions can be single versions or ranges, so be exact
OpenVEXA light document with @context, author, timestamp, version and a list of statements, each naming a vulnerability, products (often PURLs), a status and a justificationYou want small, composable statements, for example one per CVE, generated by tooling in a build pipelineImpact statements are free text and OpenVEX discourages relying on them for automation; use the justification label

A practical rule: match the format your consumer already processes. If you only have one channel, CycloneDX VEX alongside a CycloneDX SBOM keeps identifiers consistent, and CSAF suits advisory-driven customers. Our earlier post on building a VEX document for consumers walks through the authoring choices in more depth.

Here is the OpenVEX example from Safeguard's CSAF/VEX upload docs. It states that one npm package version is not affected by a CVE because the vulnerable code is not present:

{
  "@context": "https://openvex.dev/ns/v0.2.0",
  "@id": "https://example.com/vex/2024/001",
  "author": "Example Corp",
  "timestamp": "2024-01-15T00:00:00Z",
  "statements": [
    {
      "vulnerability": {
        "name": "CVE-2024-12345"
      },
      "products": [
        {
          "@id": "pkg:npm/example-package@1.0.0"
        }
      ],
      "status": "not_affected",
      "justification": "vulnerable_code_not_present"
    }
  ]
}

What the CRA and FDA expect about communicating vulnerability status

Neither regulation mandates a particular VEX format, and neither uses the word VEX in the text we read. What both do is require manufacturers to know their components, handle vulnerabilities in them, and tell users about the result. VEX is one of the cleanest ways to show that work.

EU Cyber Resilience Act

Regulation (EU) 2024/2847, the Cyber Resilience Act, sets vulnerability handling requirements for manufacturers of products with digital elements in Annex I, Part II. The points that bear on vulnerability status are:

  • Point (1): identify and document vulnerabilities and components, including by drawing up an SBOM in a commonly used, machine-readable format that covers at least the top-level dependencies.
  • Point (4): once a security update is available, share and publicly disclose information about fixed vulnerabilities, including a description, information that lets users identify the affected product, the impact, the severity and clear information to help users remediate. Publication can be delayed in duly justified cases until users have had the chance to patch.
  • Point (6): facilitate the sharing of information about potential vulnerabilities in the product and in third-party components it contains, including by providing a contact address.

Article 13(6) requires a manufacturer that finds a vulnerability in an integrated component, open source included, to report it to the component's maintainer. Article 14(8) requires a manufacturer, after becoming aware of an actively exploited vulnerability or a severe incident, to inform impacted users and any mitigation they can deploy, where appropriate "in a structured, machine-readable format that is easily automatically processable."

Timing matters. Under Article 71, the regulation applies from 11 December 2027, but Article 14, the reporting obligations, has applied since 11 September 2026. If you sell products with digital elements into the EU, the reporting half is live now.

Where VEX fits: a fixed statement is a natural machine-readable companion to the Point (4) disclosure, a not_affected statement answers the question users ask when a component in your SBOM makes the news, and an early under_investigation statement is an honest holding position. None of that makes you compliant on its own. Our batch post on SBOM generation from NTIA minimum elements to the CRA covers the SBOM half.

FDA and section 524B

For medical devices in the United States, section 524B of the Federal Food, Drug, and Cosmetic Act (21 U.S.C. 360n-2), added by the Consolidated Appropriations Act, 2023 (Pub. L. 117-328) on 29 December 2022, requires the sponsor of a premarket submission for a "cyber device" to:

  1. submit a plan to monitor, identify and address, as appropriate and in a reasonable time, postmarket cybersecurity vulnerabilities and exploits, including coordinated vulnerability disclosure;
  2. design, develop and maintain processes that provide a reasonable assurance the device and related systems are cybersecure, and make postmarket updates and patches available;
  3. provide an SBOM, including commercial, open source and off-the-shelf software components.

FDA's guidance "Cybersecurity in Medical Devices: Quality System Considerations and Content of Premarket Submissions" sets out what the agency recommends. According to the Federal Register notice of 27 June 2025, the final guidance updates the version issued on 27 September 2023, finalises the March 2024 draft on section 524B, and covers cybersecurity device design, labeling and the documentation FDA recommends in premarket submissions. Read the guidance itself for FDA's specific recommendations. The point here is narrower: a device maker who must hand FDA an SBOM and a postmarket vulnerability plan also needs a way to say, per component vulnerability, whether the device is affected. That is a VEX-shaped problem.

How Safeguard handles VEX and CSAF today

Before the step by step flows, here is where each piece lives in the product and its maturity label.

CapabilityLabelWhere it livesWhat it does for VEX
CSAF and VEX uploadGAESSCM › Integrations, filter by Upload, "Upload CSAF/VEX" cardIngests CSAF 2.0, CycloneDX VEX, OpenVEX and CSAF VEX .json files, validates them and attaches them to a project name and version
Vulnerability management, including the Mitigations tabGAProject › Vulnerabilities and Project › MitigationsRecords not applicable, false positive, workaround and risk acceptance decisions with justification, approver, evidence, scope and expiry
Reachability analysis and prioritisationGA (some languages Preview)Vulnerabilities table, Reachability and Priority columnsClassifies findings as reachable, conditionally reachable, unreachable or unknown
SBOM generation and analysis (SPDX, CycloneDX)GAProjects, Explore SBOM, export optionsProduces the version-specific SBOM your VEX statements reference
Portal (the SBOM publish and share product)GAPortal › Sharing, Customer PortalShares SBOMs with links, permissions, NDA gates, download notifications and tracking
Trust Centerearly accessCompliance › Trust CenterPublic posture page with a Documents section, subscriber updates and security contacts
Compliance and GRC suite: CycloneDX VEX and VEX Readiness frameworksGACompliance › FrameworksChecks SBOM fields VEX depends on and provides VEX controls and policy templates
Policies and gatesGAPoliciesGate results take active mitigations into account

Safeguard's file upload docs list CSAF and VEX alongside SBOMs under "Security Documents", and the SBOM generation docs list "Upload CSAF/VEX" as one of the ways a project gets its data.

Step by step: upload a supplier's CSAF or VEX to Safeguard and see findings change

This flow follows Safeguard's CSAF/VEX upload documentation. Use it when a supplier sends you a VEX file or publishes a CSAF advisory for a product you run, or when you want to load your own VEX for a project you build.

  1. Get the right file for the right version. Download the supplier's CSAF or VEX document and check, before uploading, which product identifiers and versions it covers. A VEX statement for version 4.2 says nothing about version 4.1.
  2. Check that it is one of the supported formats. Safeguard's docs list four, all as .json: CSAF 2.0 (the OASIS standard), VEX in CycloneDX format, VEX in OpenVEX format, and VEX using the CSAF VEX profile. A VEX document in any other form needs converting first.
  3. Open Integrations. In the Safeguard web app, go to Integrations from the sidebar and filter by Upload.
  4. Choose the CSAF/VEX upload. Click Connect on the Upload CSAF/VEX card.
  5. Describe the upload. Enter a Name for the upload and, optionally, a Description. Include the supplier, product and advisory ID so the audit trail reads well later.
  6. Add the file. Drag and drop the CSAF or VEX file, or click Browse. The file is validated automatically.
  7. Configure the project. Set the Project Name and the Version, then click Upload. Set these to match the product and version the statements are about. The docs do not spell out how statements are matched to existing components beyond this, so treat the project and version you enter as part of the claim.
  8. Review the result in the project. Open the project and its Vulnerabilities tab. The docs describe the purpose of a VEX upload as marking vulnerabilities as "not affected" for your products, documenting mitigation status, tracking exploitability assessments and reducing false positives in vulnerability reports. Check that the CVEs your supplier declared not affected now reflect that, and that anything marked affected or under investigation is still on your list.
  9. Record your own decision. A supplier's statement is their assertion. If you accept it, add a mitigation on the finding (Vulnerabilities tab, the row's menu, Add Mitigation) with type Not Applicable, a justification that references the supplier's document, the approver's name, the supplier's file as evidence, and a scope of this version only. If you do not accept it, leave the finding open and ask the supplier for their evidence.

If the upload fails, the docs list three errors:

  • "Invalid file format": the file is not valid JSON, does not follow CSAF 2.0 or a supported VEX schema, or has syntax errors.
  • "Schema validation failed": the structure does not match the expected schema, often because required fields are missing. Check the CSAF or VEX specification for what is required.
  • "Unsupported VEX format": the document is in a VEX form other than CycloneDX VEX, OpenVEX or the CSAF VEX profile. Convert it to one of those.

One note on the CSAF example in Safeguard's docs: it is trimmed to show the csaf_vex category, the tracking block and a known_not_affected status. A document that claims the CSAF VEX profile in full also needs a product_tree, per-vulnerability notes and an impact flag or threat for each not-affected product, as section 4.5 of the standard requires. If a supplier's file fails schema validation, those fields are the first place to look.

Where suppliers' VEX comes from

Getting the file is often the hard part. If you manage suppliers in Safeguard's TPRM (GA), you can send single or bulk SBOM requests and track them through statuses from Sent to Validated or Rejected. Ask for VEX in the same conversation; the supplier who produces the SBOM is best placed to say which of its CVEs apply. Our batch post on supplier software risk under DORA, NIS2 and M-22-18 covers that workflow.

Step by step: produce and share your own VEX for a product version

This is where honesty matters most. Safeguard's docs describe how to ingest VEX, how to record mitigations, and how to share SBOMs and documents. They do not describe a button that turns your mitigations into a VEX file, and Portal's documented export formats are SBOM, spreadsheet, document and data formats, not VEX. So the flow below uses Safeguard for the evidence, the SBOM, the validation and the distribution, and uses your own tooling or process to write the VEX document itself.

  1. Make the SBOM VEX-ready. In Compliance › Frameworks, open the VEX Readiness framework and the CycloneDX VEX framework. Both are on unless you switch them off in Compliance › Manage. Each scan checks requirements such as PURLs on components (with a CPE as a fallback), exact versions rather than ranges or "latest", hashes, a machine-readable format, a document identifier and timestamp, a recorded author, and dependency relationships. Fix those gaps first; a VEX statement that cannot be matched to a component helps nobody.
  2. Triage the finding with evidence. Open the project's Vulnerabilities tab, find the CVE and look at the Reachability column alongside EPSS and KEV. Reachability analysis (GA) classifies the finding as reachable, conditionally reachable, unreachable or unknown, as the next section explains. Decide which VEX status is true, and for "not affected", which justification you can defend.
  3. Record the decision in Mitigations. From the Vulnerabilities tab, open the row's menu and choose Add Mitigation. The form requires a Type (Risk Acceptance, False Positive, Workaround or N/A), a Justification, an Approved By value and a Scope (this version only or all versions), with optional Evidence and, for risk acceptances, an Expiration Date. For a "not affected" claim, use N/A or False Positive as the facts dictate, attach the evidence and scope it to this version only. Every change lands in the History tab.
  4. Write the VEX statement in your chosen format. Use the mitigation as the source of truth: the CVE, the product identifier from the SBOM (ideally the PURL), the exact version, the status, the justification label, and an impact statement that summarises the evidence in a sentence or two. Give the document an identifier, a version, an author and both timestamps, as CISA's minimum requirements ask.
  5. Validate it by uploading it to your own project. Run the upload flow above against your own project and version. The automatic validation catches malformed JSON and schema errors before a customer does, and you can confirm the statement lines up with the finding in your Vulnerabilities tab.
  6. Publish the SBOM to Portal and share it. In Portal (GA), publishing creates an immutable copy of the SBOM from ESSCM, and sharing distributes it onward as it is. Portal's sharing docs describe direct sharing with View, Download or Full permission, shareable links with expiry, download limits and passwords, a branded Customer Portal, per-SBOM NDA acceptance, access tracking and immediate revocation. Our batch post on publish versus share in Portal explains the difference in detail.
  7. Put the VEX where customers will look. If you run a Trust Center (early access), its Documents section lets you add a document with a category (Security or Other fit a VEX file), a Visibility of Public or Restricted, and a choice about showing it on the public page. Each file shows its size and SHA-256, which gives customers a way to check they have the exact file you published. Restricted documents are released through access requests. Our batch post on setting up a Trust Center walks through it. If you do not use the Trust Center, publish the VEX through your own advisory channel and reference the SBOM version it qualifies.
  8. Tell the people who asked. Trust Center visitors can subscribe to updates, including an "Incidents and security advisories" topic where topic selection is on. Where security contacts are switched on, "Notify about an update" emails every listed contact, and that email cannot be unsent.
  9. Keep it current. When anything changes, increment versions and update timestamps. CISA notes that refreshing the last updated timestamp without changing the status reaffirms it. Safeguard notifies 14 days and 7 days before a risk acceptance expires, and on the day.

How reachability and mitigations support "not affected" without overclaiming

Reachability is the strongest evidence most teams have for vulnerable_code_not_in_execute_path, and the easiest to overstate. Safeguard's docs describe static (call graph), dynamic (runtime collector) and configuration reachability, and four result classes. Here is how each maps to what you can honestly say:

Safeguard reachability classWhat the docs say it meansWhat you can say in VEX
ReachableA real call path exists and is instantiated at runtimeaffected, with an action statement, unless another justification applies on separate evidence
Conditionally reachableA path exists but needs a feature flag, route or configuration that is not currently enabledNot a clean "not affected" under CISA's five labels. If the setting cannot be enabled by the user, consider an impact statement explaining that; if it can, the product is affected for users who enable it
UnreachableNo call path exists in your compiled codeCandidate for vulnerable_code_not_in_execute_path, after a human reviews the evidence and the caveats below
UnknownThe analyser could not decide, for example dynamic dispatch, reflection or native codeNever "not affected". Safeguard marks these conservatively as potentially reachable, and so should you

Three caveats from Safeguard's own docs belong in every review of an "unreachable" result:

  • Language coverage varies. Static reachability is GA for JVM languages, Python, JavaScript and TypeScript, Go, Rust, C and C++, and .NET, and Preview for Ruby, PHP, and Swift and Objective-C (dynamic is also Preview for Swift and Objective-C).
  • Some vulnerabilities are data-driven. The docs say reachability is weakest for input-driven flaws, reflection or eval, and configurations the analyser cannot enumerate.
  • CSAF's definition is broad. CSAF's definition of vulnerable_code_not_in_execute_path extends to states of the product nobody anticipated. A call graph is strong evidence for that claim, but a reviewer should confirm it, especially for code loaded by plugins or configuration.

Safeguard's docs state that reachability filtering removes 60 to 80% of findings from the urgent queue, based on aggregate data across customer tenants. That is Safeguard's stated figure for prioritisation, not a guarantee, and it is not the same thing as 60 to 80% of findings being safe to declare "not affected". Prioritisation decides what you fix first; a VEX statement is a public claim to customers who will rely on it.

Mitigations are where the claim and its evidence meet. The four documented types line up with VEX like this:

  • N/A (Not Applicable) covers an unused code path, a disabled feature, a development-only component or a platform that does not apply. It is the raw material for not_affected, but a development-only component supports component_not_present only if it is absent from what you ship.
  • False Positive covers misidentified vulnerabilities, components not actually present and wrong version detection. That is CycloneDX false_positive, or often CISA component_not_present.
  • Workaround Applied covers configuration changes and compensating controls. A firewall rule in the customer's environment is not CISA's inline_mitigations_already_exist, which requires built-in protections the user cannot disable.
  • Risk Acceptance means you carry the risk. It never supports "not affected"; at most it sits behind an affected statement.

Mitigations also affect gates. Per the docs, active mitigations exclude a vulnerability from gate failures, expired mitigations do not, and policy-based mitigations apply automatically. The docs also describe Mitigation Policies under Settings, including CVE exemptions, package exemptions, a severity threshold and development-only rules. A blanket rule is not a per-version VEX judgement, so do not publish VEX derived from one without review.

Requirement vs what Safeguard does vs what you still own

Requirement or sourceWhat it asksWhat Safeguard doesWhat you still own
CISA minimum requirements: product identifiersIdentifiers that reference SBOM entriesSBOM generation (GA) with PURLs; VEX Readiness and CycloneDX VEX frameworks check PURL, version and hash coverageUsing the same identifiers in your VEX as in your SBOM
CISA: "not affected" needs a justification or impact statementOne of five justifications, or an explanationReachability (GA) and Mitigations record the evidence, approver and scopeChoosing the justification and defending it
CSAF 2.0 section 4.5 (VEX profile)csaf_vex, product tree, statuses, impact and action statementsAccepts and validates CSAF 2.0 and CSAF VEX uploads (GA)Producing valid CSAF for your own advisories
CSAF 2.0 section 7 (distribution)Provider metadata, well-known URL, TLS, signaturesNot described in Safeguard's docsRunning your CSAF provider, signing and hosting
CRA Annex I Part II (4) and Article 14(8)Disclose fixed vulnerabilities; inform users, where appropriate machine-readablyPortal sharing (GA); Trust Center documents and notifications (early access)Deciding what to disclose, when, and the reporting to authorities
FD&C Act section 524B(b)Postmarket vulnerability plan and an SBOMSBOM generation, vulnerability management, mitigations with audit trailThe plan, the premarket submission and FDA interactions
Consuming supplier VEXUse supplier assertions without blind trustUpload and validation (GA); mitigations record your acceptanceDeciding which publishers you trust and why

What Safeguard does not do

  • It does not write your VEX justification or sign the claim. Safeguard records evidence, approvals and scope, but the docs describe no VEX generator and no Portal export in a VEX format. Someone on your team decides the status, writes the statement and stands behind it, as CISA expects of an identified author.
  • It does not verify that a supplier's VEX is true. Uploads are validated for format and schema. Safeguard's docs do not describe checking a supplier's signature, re-deriving their analysis, or vouching for their claims. Whether to trust a publisher is your decision, and the CISA guidance says tools consuming VEX should validate it, involving human analysts when necessary.
  • It does not run a CSAF provider for you. CSAF section 7 describes provider metadata, well-known URLs, ROLIE feeds and OpenPGP signatures. Safeguard's docs do not describe publishing your advisories in that form, so if your customers expect a CSAF feed, you host it.
  • Trust Center is early access. Its documented features are real but newer and expanding, and its docs do not mention VEX by name; you add the file as a document.
  • It does not handle CRA or FDA reporting. Safeguard does not submit notifications to ENISA's single reporting platform, CSIRTs or FDA. It supplies the SBOM, the vulnerability data and the records; the regulatory process stays with you.
  • Reachability is not proof. Some languages are Preview, unknown results are treated as potentially reachable, and data-driven vulnerabilities can defeat call graph analysis. An "unreachable" result is evidence for a reviewer, not a statement to publish automatically.
  • It does not accept every VEX shape. The docs list four JSON formats. Anything else returns "Unsupported VEX format" and must be converted first.
  • No API flow yet. The Mitigations docs page describes /v1 REST endpoints, and its banner says those endpoints are not yet available. Use the web app flows above.

Common mistakes

Stale VEX. A "not affected" statement is true for one version at one time. Code changes, a new call path appears, and the statement quietly becomes false. Tie each statement to a mitigation scoped to that version, give reviews a date, and either reaffirm (update the timestamp) or change the status.

Wrong product identifiers. The commonest reason a VEX document does nothing is that its identifiers do not match the SBOM. A statement about pkg:npm/example-package@1.0.0 will not match a component recorded under a different PURL, a CPE only, or a name with different casing or namespace. In CSAF, every product ID in a status list must appear in the product_tree. Generate the VEX from the same SBOM you share, and check PURL coverage with the VEX Readiness framework first.

Missing or vague version ranges. CISA allows version ranges as product identifiers, and CycloneDX affects entries accept a version or a range, but a statement that says "all versions" or relies on "latest" cannot be scoped. Safeguard's CycloneDX VEX framework checks for exact component versions precisely because vague versions make a statement's scope undecidable. Say which versions the statement covers, and use the "this version only" scope on the matching mitigation.

Using "not affected" for "we patched it". If the product contains a fix, the status is fixed (CycloneDX: resolved). "Not affected" means the vulnerability never applied to that version.

Relying on impact statements alone. Machines cannot act on prose, and OpenVEX discourages it for automation. Use a justification label and add the impact statement as context.

Treating silence as a status. CISA is explicit that VEX implies no default status. If your supplier's VEX does not mention a CVE, that CVE is unresolved for you.

Confusing subcomponent and product status. State the product's status and name the subcomponent; do not mark the library itself "not affected".

FAQ

What is the difference between VEX and CSAF?

VEX is a concept with minimum data elements defined by CISA: a statement that a product is or is not affected by a vulnerability, with one of four statuses. CSAF is an OASIS standard for machine-readable security advisories, and one of its profiles is a VEX profile. A CSAF VEX document is one way to express VEX; CycloneDX VEX and OpenVEX are others.

Can I upload a VEX file into Safeguard?

Yes. CSAF and VEX upload is GA. Go to Integrations, filter by Upload, click Connect on the Upload CSAF/VEX card, add a name and the file, set the project name and version, and click Upload. The file is validated automatically.

Which VEX formats does Safeguard support?

The docs list four, all .json: CSAF 2.0, CycloneDX VEX, OpenVEX and the CSAF VEX profile. Other formats return "Unsupported VEX format".

Does Safeguard generate VEX documents automatically?

Not according to its docs. Safeguard records the evidence for a decision in the Mitigations tab, gives you reachability analysis, and validates any VEX you upload, but the docs describe no VEX generator or VEX export. You write the statement, and you can upload it back to your own project to validate it.

What VEX justification should I use when the vulnerable function is never called?

vulnerable_code_not_in_execute_path in CISA, CSAF and OpenVEX terms, or code_not_reachable in CycloneDX. Use it only when the evidence holds up, for example a reviewed "unreachable" result in a language where Safeguard's static reachability is GA, and never on an "unknown" result.

Does the EU Cyber Resilience Act require VEX?

The CRA text does not name VEX. It requires a machine-readable SBOM, vulnerability handling, disclosure of fixed vulnerabilities and, under Article 14(8), informing users after actively exploited vulnerabilities, where appropriate in a structured, machine-readable format. VEX is a natural way to meet the machine-readable part. Article 14 has applied since 11 September 2026, and the rest of the regulation applies from 11 December 2027.

Does the FDA require VEX for medical devices?

Section 524B of the FD&C Act requires an SBOM and a plan to monitor, identify and address postmarket vulnerabilities for cyber devices. It does not name VEX. Read FDA's premarket cybersecurity guidance, finalised in its updated form in June 2025, for what the agency recommends about documenting vulnerabilities in SBOM components.

Can I share VEX through Safeguard's Trust Center?

Trust Center is early access. Its Documents section lets you add a file with Public or Restricted visibility and shows each file's size and SHA-256, and restricted files are released through access requests. The Trust Center docs do not mention VEX specifically, so you add the VEX file as a document, typically in the Security category.

Fix it without waiting for upstream

A VEX statement tells customers where they stand on a vulnerability; for every statement that has to say "affected", the next question is how fast it can become "fixed". The block below describes the remediation paths Safeguard offers once you know a component in your product is affected.

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.

3. Gold Registry: start from components that are already fixed

registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would help

The first demo connects Claude to the Safeguard MCP server (GA) with OAuth and shows how you choose which Safeguard tools Claude can use. For VEX work, an assistant connected this way can help you review a project's findings and draft the reasoning behind a status; the statement you publish still needs a human author.

Click through it at your own pace, or open it full screen.

The second demo is a real session in the Safeguard CLI (GA): you ask it to fix a lodash CVE in a repository, it reads the finding and the advisory, asks before each command, updates the dependency, runs the install and tests with your approval and pushes nothing. That is the path a VEX statement takes from affected to fixed: once the fix ships in a new version, you issue a fixed statement for that version instead of defending an exception.

Click through it at your own pace, or open it full screen.

If you want to try the upload and mitigation flows yourself, download Safeguard at https://safeguard.sh/download and follow the docs at https://docs.safeguard.sh/docs . For related reading, see validating CycloneDX, SPDX and VEX with Safeguard, using SBOMs in incident response and our batch post on prioritising vulnerabilities with reachability, EPSS and KEV.

Quick check

A supplier's VEX document covers 40 CVEs in a library you use but says nothing about a 41st CVE your scanner reports. What is the status of the 41st?

Unknown. CISA's minimum requirements state that VEX does not specify, assume or imply any default status that is not explicitly provided. The 41st CVE stays open in your triage until the supplier issues a statement or you complete your own analysis.

Safeguard's reachability analysis marks a finding as "Unknown" because the call happens through reflection. Can you publish "not affected" with the justification vulnerable_code_not_in_execute_path?

No. Safeguard's docs say Unknown results are marked conservatively as potentially reachable and are not suppressed. Without other evidence, such as a review showing the vulnerable code is not compiled in, the honest status is under_investigation or affected.

Sources

Last reviewed: 24 October 2026. Product capabilities change; check docs.safeguard.sh for the current state.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.