VEX and SBOMs: Triaging Vulnerabilities That Matter

Engineering
Share on LinkedIn Share on X Share on Reddit Share on HN Share on Bluesky

title: "VEX and SBOMs: Triaging Vulnerabilities That Matter" slug: "vex-vulnerability-triage-sbom" description: "How VEX and SBOMs cut CVE noise: assert which vulnerabilities are actually exploitable in your product, automate triage, and stop drowning scanners in false positives." datePublished: "2026-02-01" dateModified: "2026-07-17" tags:



title: "vex-vulnerability-triage-sbom" slug: "vex-vulnerability-triage-sbom" description: "" datePublished: "2026-07-17" dateModified: "2026-07-17" tags:



title: "vex-vulnerability-triage-sbom" slug: "vex-vulnerability-triage-sbom" description: "" datePublished: "2026-07-17" dateModified: "2026-07-17" tags:



title: "vex-vulnerability-triage-sbom" slug: "vex-vulnerability-triage-sbom" description: "" datePublished: "2026-07-17" dateModified: "2026-07-17" tags:



title: "vex-vulnerability-triage-sbom" slug: "vex-vulnerability-triage-sbom" description: "" datePublished: "2026-07-17" dateModified: "2026-07-17" tags:



title: "vex-vulnerability-triage-sbom" slug: "vex-vulnerability-triage-sbom" description: "" datePublished: "2026-07-17" dateModified: "2026-07-17" tags:



title: "VEX and SBOMs: Triaging Vulnerabilities That Matter" slug: "vex-vulnerability-triage-sbom" description: "How VEX and SBOMs cut CVE noise: assert which vulnerabilities are actually exploitable in your product, automate triage, and stop drowning scanners in false positives." datePublished: "2026-02-01" dateModified: "2026-07-17" tags:



If you've run a container scanner against a real production image lately, you know the feeling: 300 CVEs reported, red everywhere, and a nagging certainty that maybe five of them actually matter. VEX — Vulnerability Exploitability eXchange — is the discipline and the data format for separating those five from the other 295. It's a machine-readable way to assert, per vulnerability, whether a CVE is genuinely exploitable in your product, so you stop treating "present in the bill of materials" as identical to "dangerous."

I got religious about this after watching a team burn a full sprint chasing scanner findings, only to discover that most were in code paths their service never executed. SBOMs told them what was inside; nothing told them what to fear. VEX is that missing layer. Here's how the two fit together and how to run triage that respects your engineers' time.

The noise problem VEX solves

A CVE is filed against a component and version. It says nothing about how you use that component. Your image might contain a vulnerable libxml2, but if your service never parses untrusted XML through the affected function, the exploit has no path to reach. The scanner can't know that — it matches versions against a vulnerability database, full stop.

The result is a signal-to-noise disaster. When 95% of findings are non-exploitable, engineers learn to ignore the scanner entirely, which means the 5% that do matter get ignored too. Alert fatigue in vulnerability management isn't a nuisance; it's a security failure, because it trains your team to dismiss the tool that would have caught the real breach.

SBOM first, then VEX on top

The two artifacts have distinct jobs:

A VEX status is one of a small set: not affected, affected, fixed, or under investigation. The interesting one is not affected, which should come with a machine-readable justification — for example, vulnerable_code_not_in_execute_path or component_not_present. That justification is what lets a downstream consumer trust your assertion instead of re-triaging everything themselves.

If you're not yet producing SBOMs at build time, start there — the practices in container image security and SBOMs are the prerequisite. VEX without an SBOM has nothing to annotate.

What a VEX assertion looks like

VEX can be expressed in several formats — CycloneDX has native VEX support, and there's the OpenVEX spec for a minimal standalone format. An OpenVEX statement is refreshingly small:

{
  "@context": "https://openvex.dev/ns/v0.2.0",
  "@id": "https://example.com/vex/2026-0001",
  "author": "Security Team <[email protected]>",
  "timestamp": "2026-02-01T09:00:00Z",
  "statements": [
    {
      "vulnerability": { "name": "CVE-2025-12345" },
      "products": [
        { "@id": "pkg:oci/payments-api@sha256:abc123" }
      ],
      "status": "not_affected",
      "justification": "vulnerable_code_not_in_execute_path"
    }
  ]
}

That's the whole idea: a signed, timestamped, machine-readable claim that CVE-2025-12345 is present but not exploitable in this specific artifact, with a reason a tool can act on. Your scanner or policy engine reads the VEX and suppresses that finding automatically instead of asking a human to re-investigate it every scan.

Triage that scales

The manual version of triage — a person reading each CVE and deciding — does not scale past a handful of services. The workflow that does looks like this:

  1. Generate the SBOM at build time, attached to the artifact so it's always current.
  2. Scan the SBOM, not the running system, so results are reproducible.
  3. Triage each new finding once, recording the decision as a VEX statement.
  4. Re-apply VEX on every subsequent scan so previously-triaged findings are suppressed automatically.
  5. Re-investigate only when the SBOM or the CVE changes.

The leverage is in step 4. A finding you've marked not_affected with a solid justification never bothers a human again unless the underlying facts change. Over a few months, your scanner output collapses from hundreds of lines to a short list of genuinely new, genuinely relevant issues.

Without VEX With VEX
Every scan re-surfaces all CVEs Triaged CVEs stay suppressed
Humans re-triage the same findings Decide once, record, automate
Alert fatigue → scanner ignored Short, trustworthy signal
No shared context downstream Consumers inherit your assertions

The honest tradeoffs

VEX is not free, and I've seen it misused. The biggest risk is a rubber-stamp culture — teams marking everything not_affected to make the dashboard green without doing the reachability analysis. A VEX statement is a security claim; if you can't articulate the justification, you haven't triaged, you've lied to your future self. Require a real justification code and, ideally, a link to the analysis.

The second issue is staleness. A not_affected verdict is true given the current code. Refactor a service so it now calls the vulnerable path, and your VEX is silently wrong. Tie VEX validity to the artifact digest (as in the example above) so a rebuild forces re-evaluation rather than carrying a stale assertion forward.

And VEX is a complement to remediation, not a substitute. "Not exploitable" is a reason to deprioritize, not to never patch — an unpatched dependency is a future exploit path when your code changes around it. This all sits inside the broader provenance and integrity story covered in supply chain security with SLSA and SBOMs; VEX handles "which known issues matter," while SLSA handles "can I trust how this was built."

Where to start

If you're drowning in scanner output today, the highest-leverage move is not buying a fancier scanner — it's adding the VEX layer to the SBOMs you (hopefully) already produce. Start with your most-scanned, noisiest service. Triage its current findings once, record the decisions as VEX, wire the scanner to consume them, and watch the daily noise drop. Then make VEX generation part of the build so new services inherit the discipline.

The payoff isn't a prettier dashboard. It's that when a real, reachable, critical vulnerability lands, your team actually sees it — because you've spent the effort making sure the scanner only shouts when it should.

VEX status semantics

not_affected requires justification enum from OpenVEX spec — free-text-only rejected by Grype 0.74 verify. Regenerate VEX when SBOM changes even if CVE id unchanged; stale VEX breaks CI verify step silently passing with wrong attachment filename.

VEX status semantics

not_affected requires justification enum from OpenVEX spec — free-text-only rejected by Grype 0.74 verify. Regenerate VEX when SBOM changes even if CVE id unchanged; stale VEX breaks CI verify step silently passing with wrong attachment filename.

CSAF and machine-readable advisories

CSAF 2.0 JSON advisories extend VEX with product tree, remediations, and references consumable by enterprise GRC tools. Export CSAF alongside CycloneDX SBOM for customers requiring automated ingestion into ServiceNow or Kenna.

Structure releases:

release-1.4.2/
  sbom.cdx.json
  vex-1.4.2.csaf.json
  checksums.sha256

Sign with cosign or GPG. Customers verify integrity before merging into their vulnerability management database.

Developer workflow integration

Pre-commit hooks generating SBOM on every build are noisy—generate SBOM at release tag, attach to GitHub Release assets. Dependabot and Renovate handle day-to-day dependency bumps; SBOM diff between releases shows component changes for security review.

Train engineers: not_affected requires justification text a stranger understands in six months. "Doesn't apply" is not documentation.

Reducing scanner noise without lying

Common legitimate not_affected cases:

Questionable cases needing patch anyway:

Resources

Field notes on vex vulnerability triage sbom

Supply-chain controls for vex vulnerability triage sbom only work when attestations are verified in the deploy path, not merely generated for auditors.

For vex vulnerability triage sbom:

Tabletop a compromised builder scenario — detection time and revoke path matter more than tool logos.

Signal Target Alarm
Latency p99 Team-defined SLO Page on burn rate
Error rate Baseline − noise Ticket if sustained
Cost per 1k ops Budget cap Weekly review

Ownership and on-call for vex vulnerability triage sbom

Reviewers should challenge assumptions encoded in vex vulnerability triage sbom: defaults copied from tutorials, timeouts that exceed upstream SLAs, and authz checks applied only on the primary UI path. Require a short threat or failure note in the PR when the change touches a trust boundary.

Concrete probes:

  1. Scenario C for vex vulnerability triage sbom: traffic 3× baseline — prove autoscaling or shedding keeps the golden journey healthy.
  2. Scenario A for vex vulnerability triage sbom: partial dependency outage — prove clients degrade gracefully and retries do not amplify load.
  3. Scenario B for vex vulnerability triage sbom: bad config shipped — prove rollback within the declared RTO without data corruption.

Rollout sequence that worked for vex vulnerability triage sbom

Roll out vex vulnerability triage sbom behind a flag or weighted route when possible. Start with internal users or a low-risk geography. Watch the signals in the table for at least one full business cycle before calling the migration done. Keep the previous path warm until error budgets stabilize.

Document the owner, the dashboard, and the single command that reverts the change. If that sentence is hard to write, the design is not ready for production traffic.

Caching interactions with vex vulnerability triage sbom

Detail 1 (841): for vex vulnerability triage sbom, define the contract between producers and consumers explicitly — payload shape, timeout, and idempotency key. When caching interactions with vex vulnerability triage sbom becomes painful, it is usually because that contract was implicit.

I keep a short matrix: who can break vex vulnerability triage sbom, how we detect it within five minutes, and who is paged. Update the matrix when ownership moves. Add one synthetic check that exercises the failure path, not only the happy path. Prefer checks that run continuously over quarterly manual reviews that everyone skips under deadline pressure.

If you only remember one thing about vex vulnerability triage sbom: optimize for reversible decisions. Reversibility beats cleverness when the incident channel is busy and the blast radius is unclear.

Multi-tenant concerns in vex vulnerability triage sbom

Detail 2 (866): for vex vulnerability triage sbom, define the contract between producers and consumers explicitly — payload shape, timeout, and idempotency key. When multi-tenant concerns in vex vulnerability triage sbom becomes painful, it is usually because that contract was implicit.

I keep a short matrix: who can break vex vulnerability triage sbom, how we detect it within five minutes, and who is paged. Update the matrix when ownership moves. Add one synthetic check that exercises the failure path, not only the happy path. Prefer checks that run continuously over quarterly manual reviews that everyone skips under deadline pressure.

If you only remember one thing about vex vulnerability triage sbom: optimize for reversible decisions. Reversibility beats cleverness when the incident channel is busy and the blast radius is unclear.

Frequently asked questions

What is the main production risk with vex vulnerability triage sbom?

Teams ship without field measurement—vex vulnerability triage sbom failures appear as silent UX regressions, cost drift, or audit findings rather than clear errors.

When should we prioritize vex vulnerability triage sbom?

Prioritize when user research, CrUX, support tickets, or compliance requirements show pain on critical paths—not when a checklist mentions it abstractly.

How do we validate vex vulnerability triage sbom changes?

Baseline RUM before changes, compare p75 after deploy, and keep rollback via feature flags or cache purge documented in the PR.

Hiring a senior Android / Flutter engineer?

I architect and ship production mobile software — Kotlin, Jetpack Compose, Flutter — for robotics, EV infrastructure, fintech, and real-time systems. Open to remote roles in Europe and the US.

Get in touch →