Vulnerability Management

Modern VEX Vulnerability Management: Patch Only the 10% of CVEs That Actually Matter

Every vulnerability scan produces a pile of CVE findings, and most of them don't actually affect your product. VEX makes exploitability machine-readable - here's what it saves in developer time, how it fits CRA compliance, and why sharing assessments across a community is the real lever.

Frédéric Noppe
Frédéric NoppeCOO & Software Security Compliance Expert
Published Last updated 11 min read

Every vulnerability scan of your software produces a pile of CVE findings, and most of them don’t actually affect your product, either because the vulnerable code path is never called, or because an existing safeguard already prevents exploitation. The Vulnerability Exploitability eXchange (VEX) is the standard for capturing exactly that, in a machine-readable way. This article explains the concept, works out how much developer time is actually on the table, places VEX within your Cyber Resilience Act obligations, and uses container.gov.de as an example of why sharing these assessments in particular is the real lever.

A real example: the scanner reports 200+ open vulnerabilities in a container image. A developer works through them, and after two days the verdict is in: the vast majority simply don’t matter for the software actually shipped. The vulnerable components sit in the image, but the affected function is never invoked. The next scan runs, and the same discussion starts over. What’s frustrating here isn’t the vulnerability scanner, which does its job (mostly just parsing and cross-referencing package manager files, there’s no more magic to it than that) reasonably well (my colleague Refaei wrote an entire research paper on its detection rates). What’s frustrating is that the answer to “does this specific vulnerability affect us?” gets worked out from scratch nearly every time, and is never recorded anywhere a machine can act on. That is exactly the problem VEX solves.

What VEX Is, and What It Isn’t

The Vulnerability Exploitability eXchange is a machine-readable format in which a vendor states, for a specific vulnerability in a specific product, whether it is exploitable. CISA published the minimum requirements in April 2023, as version 1.0.0, developed by an international working group that, notably, also included Germany’s BSI.

The clean separation from an SBOM matters here, and it trips up more people than you’d expect:

The SBOM says what’s in your software. VEX says whether it affects you.

That distinction isn’t an academic footnote, it’s written into the standards. BSI TR-03183-2 explicitly requires that an SBOM contain no vulnerability information, and points to CSAF and VEX for that purpose instead. The reason lies in the nature of the data: an SBOM is a static snapshot of a software version. Vulnerability information is dynamic and changes daily. Cram both into one document, and you get a document that’s permanently out of date.

Recap: the reasoning chain behind a vulnerability finding, from CVE to affected library to actual usage
The typical thought process when reviewing a reported vulnerability (CVE).
The same reasoning chain, annotated to show which step is the hard part and which is easy
The hard part is working out whether a library is actually affected, and whether the vulnerability propagates through the dependency tree. That usually takes far more effort than the question of whether the vulnerable parts of a library you use yourself are actually used at all.

And one more distinction worth stressing: VEX is not a substitute for patching. It’s a prioritization tool. Where a fix is available and reasonable to apply, applying it is still the right answer. VEX answers the question of what to do when no fix exists, when applying one isn’t practical, or when there’s simply no action to take because the vulnerability doesn’t affect you in the first place.

Four Statuses, Five Justifications

A VEX statement assigns exactly one status to a vulnerability for one or more products:

  • not_affected - No action required, the product is not affected.
  • affected - Action is recommended, an action_statement is mandatory.
  • fixed - The stated product versions contain the fix.
  • under_investigation - The assessment is still in progress.

The interesting case is not_affected. Here the standard requires a justification drawn from a fixed set of five values, and that standardization is exactly what makes the statement machine-actionable:

  • component_not_present - The vulnerable component simply isn’t part of the shipped product. Typical for build- or test-time dependencies that a multi-stage build discards again.
  • vulnerable_code_not_present - The library is included, but the vulnerable code isn’t. The most common reason in practice is backporting: Debian ships a fix without changing the version string the scanner reads.
  • vulnerable_code_not_in_execute_path - The code is there, but it’s never called. This is the justification you can prove most rigorously, for example via a symbol analysis of the binary.
  • vulnerable_code_cannot_be_controlled_by_adversary - The code runs, but no attacker-controlled input ever reaches it. The hardest justification to make, since it rests on a claim about the entire trust boundary.
  • inline_mitigations_already_exist - An existing safeguard prevents exploitation: an input filter, a WAF rule, a seccomp profile.

My recommendation: work through this list in exactly that order. The earlier justifications are the stronger claims and the easier ones to verify. And when you use inline_mitigations_already_exist, always name the concrete mitigation and where it lives, a mitigation nobody can find again isn’t auditable. If it’s later removed, the justification silently becomes false.

A minimal OpenVEX document looks like this:

openvex.json
{
  "@context": "https://openvex.dev/ns/v0.2.0",
  "author": "Security Team <security@example.com>",
  "timestamp": "2026-08-09T10:00:00Z",
  "version": 1,
  "statements": [
    {
      "vulnerability": { "name": "CVE-2025-12345" },
      "products": [
        { "@id": "pkg:oci/my-app@sha256:abc123..." }
      ],
      "status": "not_affected",
      "justification": "vulnerable_code_not_in_execute_path",
      "impact_statement": "The affected parser function is never called by the application."
    }
  ]
}

CSAF, OpenVEX, and CycloneDX VEX are the available formats. One note that matters for practical use (before you run into an unwelcome surprise about missing functionality): only CSAF and OpenVEX carry the standardized justification in a form the recipient’s tooling can act on automatically. CycloneDX VEX only conveys that you consider the finding a false positive, plus your free text, the justification is there for a human to read, not a machine to evaluate. If machine-readability matters to your recipients, such as customers or fellow engineers, give them CSAF or OpenVEX.

The Math: How Much Time Is Actually at Stake

Now for the part that matters most to decision-makers and budget owners: how big is the efficiency lever, really?

Two orders of magnitude help frame it. Commercial SCA vendors report that 70 to 80 percent of (vulnerable) dependencies in an application are never actually referenced, the code sits in the artifact but is never called. Two empirical studies back this up for the specific question of whether the vulnerable function is actually reachable. A function-level study of npm/JavaScript packages by Zapata et al. (2018) found that up to 73.3 percent of affected clients weren’t actually at risk in practice, because they never called the vulnerable function. A considerably larger 2026 study (KAUST) across 2,414 open-source repositories in Python, Rust, Ruby, and PHP measured a 92.0 percent false-positive rate among downstream vulnerability scanners, and identified unreachable code as the main cause. Depending on the study, language, and ecosystem, then, roughly 73 to 92 percent of reported findings turn out to be false positives, meaning the vulnerable functions are never called. What still matters for the calculation is the effort per case: manually triaging a single finding takes an experienced developer about ten minutes on average.

Let’s run the numbers on a realistic example. A product with 400 open findings, re-assessed every quarter:

400 findings × 10 minutes ≈ 67 hours per quarter (assuming you even want to review your software that infrequently). Over a year: roughly 267 hours, nearly seven person-weeks. For a single product.

And here’s the actual point: in our example, this work gets repeated every quarter without VEX. Not because anything changed, but because the result of the last assessment isn’t recorded anywhere a machine can read. With five products sharing an overlapping technology stack, you’re assessing the same CVE in the same library five times, in parallel.

With VEX, every vulnerability gets assessed once, based on its reachability path. The decision becomes an artifact: versioned, justified, signable, reusable. The next scan recognizes it and never puts the finding back in the queue.

The economic effect here isn’t primarily the saved hour. It’s the shift: your developers spend their time on the ten vulnerabilities that are actually exploitable, instead of the 390 that aren’t. Since triaging software vulnerabilities, especially false positives, isn’t exactly a favorite task among developers, it’s not just budget owners who benefit from this time saved, but the engineers themselves.

VEX and CRA Compliance: Where This Stops Being Optional

This is where it gets concrete for anyone implementing the Cyber Resilience Act. Let’s look at the relevant provisions.

Annex I, Part I, Section (2)(a) requires that products be placed on the market without known exploitable vulnerabilities. The word “exploitable” carries the entire weight of that sentence. The CRA doesn’t actually require your product to be free of CVEs, which would be unreachable for nearly any real-world commercial software product. It requires that you’ve assessed exploitability. That assessment isn’t busywork, it’s a precondition for market access.

So how do you prove to a market surveillance authority that you actually performed that assessment? A comment on a Jira ticket is weak evidence. A signed, timestamped VEX document with a standardized justification is strong evidence.

Annex I, Part II requires that you identify, document, and publish information about fixed vulnerabilities. CSAF is built exactly for this, and a CSAF document can simultaneously be a valid VEX document.

Article 14 brings the reporting obligations, which already take effect on September 11, 2026: 24 hours for the early warning on actively exploited vulnerabilities. If you have to state, credibly, within a day whether and how your product is affected, you need the exploitability assessment done before the incident, not on the day of it. You need it maintained and retrievable ahead of time.

The compliance time savings show up in two places: you save the repeated assessment work, and you save the effort of producing evidence, because the evidence becomes a byproduct of your normal workflow instead of a scramble before an audit.

A pleasant side effect for sales: a public VEX URL replaces the recurring customer email asking “are you affected by CVE-XY?”

Crowdsourced VEXing: The Real Lever

So far we’ve saved time within a single company. Now it gets even more interesting.

When the same library sits inside thousands of products, which it does (think Log4j or OpenSSL), it usually got there the same way: through the same intermediate library, in the same version, along the same call path. Which means thousands of teams are independently answering exactly the same question, right now. With the same result. That is, to put it mildly, not a particularly efficient allocation of security expertise (we have far more interesting problems to solve).

What is shareable here isn’t the blanket claim “this CVE is harmless”, but the assessment of one specific dependency path. Anyone carrying the same subtree in their SBOM gets an answer to a question they would otherwise have to work through themselves.

The escalation logic is simple: once per team → once per company → once per community. Every stage multiplies the time saved.

Sharing a vulnerability assessment as a VEX document with a library and a downstream product
Once made, an assessment can be passed on as a VEX document, to the library itself and to every product built on top of it.

You can currently watch this play out in practice in Germany at container.gov.de. As part of the Secure Government Container Initiative (SGCI) run by ZenDiS and openCode, hardened container images are provided there for German public-sector agencies. The underlying idea is exactly the one described above: instead of every agency hardening and assessing its own images, they are maintained together, as a community.

The compliance requirement is notably concrete. For an image to be listed, every known vulnerability of high or critical severity must be explicitly assessed. The VEX document is attached to the image itself as an in-toto attestation with the predicate type https://cyclonedx.org/vex, signed with cosign, not as a loose file sitting alongside it. Whoever pulls the image gets the assessment with it.

The effect: an agency that uses a base image from the registry inherits the maintainer’s vulnerability assessments. The work was done once, not re-done inside every organization.

What About Trust?

Here we need to pump the brakes on the enthusiasm for a moment, because shared assessments raise two questions worth taking seriously.

First: an assessment holds for the path, not for the component. vulnerable_code_not_in_execute_path always refers to one specific dependency path. If an assessment records that the vulnerable function is never reached via your-app → http-client → openssl, that stays true no matter how much code you write on top of that HTTP client. Pull in a second module later that talks to OpenSSL directly, and your-app → own-tls-module → openssl is a different path, and therefore a finding of its own. The borrowed assessment doesn’t become wrong, it simply doesn’t cover this case. Assessments from others hold for exactly the subtrees they were made for, and it is on you to check that yours really is the same one.

Second: provenance. The CISA standard requires VEX documents to be signed, with the author’s identity cryptographically tied to the signature. That only tells you who made an assessment, though, not whether it is correct: an attacker would be more than happy to confirm for you, properly signed, that a vulnerability doesn’t affect you. The way out is not to rely on any single source in the first place, but to collect assessments from many organizations for the same dependency path and derive a majority decision from them. So that this vote does not become the attack surface itself, not every vote counts the same: established organizations carry more weight, repeat votes from the same person lose weight rapidly, brand-new accounts are not allowed to vote yet, and when there are too few votes or no clear majority the system deliberately issues no recommendation at all. My colleague Dennis Tuan Anh Quach worked this approach out in Developing a Trust-Based Knowledge-Based Collaborative Filtering Hybrid Recommender System to share vulnerability management decisions in DevGuard.

How DevGuard Implements This

We built DevGuard for exactly this workflow, so here’s what the tool actually does.

  • Assess, don’t just dismiss. For a dependency finding, DevGuard shows the path to the vulnerable component as a graph. Every edge is labeled with the assumption that the vulnerable function gets called. If you know a specific edge doesn’t apply, you click it, and that creates a VEX rule that closes out not just this one finding, but every future one that arrives via the same dependency path.
  • Rules, not one-offs. A VEX rule pairs a CEL expression with a decision and applies it to every matching finding, existing and future alike. A playground shows, before you save, how many vulnerabilities a new expression will touch.
  • Import from suppliers. Your suppliers’ VEX documents can be uploaded as a file or attached permanently via URL; DevGuard auto-detects CycloneDX, CSAF, and OpenVEX, and turns every statement into a rule. If you don’t fully trust the source, just enable Paranoid Mode: imported rules then stay inactive until you approve them.
  • Crowdsourced recommendations. When enough independent organizations write the same rule for a vulnerability, it surfaces as a recommendation. It’s weighted by an organization’s trust score, and repeated votes from the same author are dampened, so a single account can’t manufacture consensus. And nothing is adopted automatically. You still create the rule yourself.
  • Export and evidence. From the same decisions, DevGuard generates CycloneDX VEX, OpenVEX, and CSAF, as a download or as an always-current public URL. For CSAF, the full Trusted-Provider structure is delivered, including OpenPGP signatures and checksums per advisory.

That this approach holds up is visible in the fact that DevGuard, as an openCode platform service, sits behind container.gov.de’s VEX attestation.

Conclusion

VEX doesn’t solve a technical problem, it solves an organizational one: it makes a security decision, once made, shareable with others. The assessment effort exists anyway, and today it gets paid for again in every review, in every project. Much of that duplicated work can be saved once the results are shared, freeing up valuable engineering time for the problems that genuinely deserve it.

For CRA compliance, add that the exploitability assessment isn’t optional. Annex I, Part I, (2)(a) requires it at its core, and starting September 2026 the reporting deadlines require that it’s available fast. Whoever maintains it as a machine-readable, signed document has already delivered the proof by the time the question gets asked.

One concrete step for this week: take the product with the most open findings, pull its ten oldest ones, and check how many times they’ve already been assessed. If the answer is “more than once,” you’ve just found your business case.

Frequently Asked Questions

What is VEX in vulnerability management?

VEX (Vulnerability Exploitability eXchange) is a machine-readable format in which a vendor states whether a known vulnerability in their product is actually exploitable. A statement assigns a CVE exactly one of four statuses: not_affected, affected, fixed, or under_investigation. CISA published the minimum requirements in April 2023 as version 1.0.0, developed by an international working group that included Germany's BSI.

What's the difference between an SBOM and a VEX document?

An SBOM says what's in your software; VEX says whether it affects you. The SBOM is a static inventory of every component in one software version, while VEX dynamically assesses exploitability, which changes daily. Germany's BSI TR-03183-2 explicitly requires that an SBOM contain no vulnerability information at all, pointing to CSAF and VEX instead.

Is VEX mandatory for CRA compliance?

The Cyber Resilience Act doesn't name VEX explicitly, but it requires essentially the same thing. Annex I, Part I, Section (2)(a) requires products to be placed on the market without known exploitable vulnerabilities, so you have to assess exploitability and prove it. A signed, timestamped VEX document is the strongest evidence you can offer a market surveillance authority.

Which justifications are allowed when a vulnerability isn't exploitable?

For the status not_affected, the standard defines five: component_not_present, vulnerable_code_not_present, vulnerable_code_not_in_execute_path, vulnerable_code_cannot_be_controlled_by_adversary, and inline_mitigations_already_exist. Work through them in that order, since the earlier ones are the stronger and more easily verifiable claims, and with inline_mitigations_already_exist always name the concrete mitigation and where it lives. Without a justification, the standard instead requires a written impact_statement.

Can I just adopt VEX assessments from the community?

Only after checking them. A VEX statement applies to a specific dependency path, not to the component on its own. It carries over only when your subtree is the same, and says nothing about an additional path reaching that library. Never pull unsigned documents from unclear sources into your pipeline: the author's identity should be cryptographically tied to the signature.

References

  1. Cybersecurity and Infrastructure Security Agency (CISA). (2023). Minimum Requirements for Vulnerability Exploitability eXchange (VEX), Version 1.0.0.
  2. CISA. (2022). Vulnerability Exploitability eXchange (VEX) - Status Justifications.
  3. Bundesamt für Sicherheit in der Informationstechnik (BSI). (2025). Technical Guideline TR-03183 - Part 2: Software Bill of Materials (SBOM), Version 2.1.0.
  4. European Parliament and Council. (2024). Regulation (EU) 2024/2847 on horizontal cybersecurity requirements for products with digital elements (Cyber Resilience Act).
  5. Regulation (EU) 2024/2847 of the European Parliament and of the Council of 23 October 2024 (Cyber Resilience Act), Annex I.
  6. ZenDiS / openCode. (2026). How-to: Creating a VEX Attestation.
  7. ZenDiS / openCode. (2026). Understanding the Vulnerability Exploitability eXchange (VEX).
  8. ZenDiS / openCode. (2026). Secure Government Container Initiative - Documentation.
  9. Help Net Security. (2025). 91% noise: A look at what’s wrong with traditional SAST tools.
  10. Foo, D. et al. (2019). The Dynamics of Software Composition Analysis. arXiv:1909.00973.
  11. Zapata, R. E., Kula, R. G., Chinthanet, B., Ishio, T., Matsumoto, K., and Ihara, A. (2018). Towards Smoother Library Migrations: A Look at Vulnerable Dependency Migrations at Function Level for npm JavaScript Packages. 2018 IEEE International Conference on Software Maintenance and Evolution (ICSME), 559-563.
  12. Zhou, L., Dacier, M., and Konstantinou, C. (2026). A Reality Check on SBOM-based Vulnerability Management: An Empirical Study and A Path Forward. Proceedings of the Sixteenth ACM Conference on Data and Application Security and Privacy (CODASPY), 255-268.
  13. OpenSSF. OpenVEX Specification.
  14. OASIS. Common Security Advisory Framework (CSAF) 2.0 - VEX Profile.
  15. DevGuard Documentation. Working with VEX in DevGuard.
Frédéric Noppe
Frédéric NoppeCOO & Software Security Compliance Expert

Frédéric Noppe is COO at L3montree Cybersecurity and a certified ISO 27001 Lead Auditor, holding a Master's in Cybersecurity Management with a thesis on the EU Cyber Resilience Act (CRA). He regularly speaks on CRA compliance and security governance at conferences such as the NIS-2 Congress and the LSZ CISO Days.

View full profile

Questions or feedback? Get in touch directly!

Send us an email