SBOM and VEX: CycloneDX vs SPDX for Software Supply Chain Vulnerability Triage (2026)
A scanner reports 412 vulnerabilities in a container image. Your security team has two engineers and a sprint. Somewhere in that list are the three findings that matter, and hundreds that are technically true and practically irrelevant: a CVE in a library that is present on disk but never loaded, a flaw in a Windows-only code path inside a Linux build, a bug already patched by a distribution backport that the scanner cannot see. The inventory told you what is in the software. It did not tell you what is exploitable.
That gap is exactly what SBOM VEX workflows close. A software bill of materials (SBOM) is the machine-readable ingredient list; a Vulnerability Exploitability eXchange (VEX) statement is the supplier’s signed assertion about whether a given vulnerability actually affects a given product. This guide compares the two dominant SBOM formats, CycloneDX and SPDX, then builds the pipeline that turns inventory plus exploitability context into a short, defensible triage queue.
What this covers: what an SBOM does and does not prove, CycloneDX vs SPDX on data model and tooling, VEX statuses and formats, a reference pipeline from build to attestation to triage, a worked noise-reduction example, regulatory context, and the failure modes that make SBOM programmes disappoint.
Context and Background
The modern SBOM conversation started with a regulatory push and a string of painful incidents. After the SolarWinds compromise and Log4Shell, the US government’s Executive Order 14028 (May 2021) directed agencies and their suppliers toward software transparency, and the US National Telecommunications and Information Administration (NTIA) published “The Minimum Elements for an SBOM” in July 2021. That document defines seven baseline data fields: supplier name, component name, component version, other unique identifiers, dependency relationship, author of the SBOM data, and timestamp. It also names three automation formats it considers acceptable: SPDX, CycloneDX and SWID tags. The Cybersecurity and Infrastructure Security Agency (CISA) has continued to refine this guidance since; check its current publication before treating the 2021 list as final, because updated minimum-element drafts have circulated since.
The two formats that won in practice are SPDX and CycloneDX. SPDX (Software Package Data Exchange) comes from the Linux Foundation and began as a licence-compliance format; version 2.x is standardised as ISO/IEC 5962:2021. CycloneDX comes from the OWASP community and was security-first from the start; its 1.6 specification became the basis of Ecma International standard ECMA-424. Both are now mature, both have JSON serialisations, and both are supported by every serious generator. The choice is less about correctness and more about which downstream consumers you must satisfy.
Inventory alone, though, has a measurable problem. Scanners match component identifiers (a package URL such as pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1, or a CPE string) against vulnerability databases such as the National Vulnerability Database (NVD), the GitHub Advisory Database or OSV. A match means “this version string appears in an advisory range”. It does not mean the vulnerable function is reachable, that the vulnerable configuration is enabled, or that a distribution has not already backported the fix. The result is a flood of findings dominated by false positives from an exploitability standpoint, and that is the problem VEX was created to address. If you are building the trust chain around the artefacts themselves, our guide to SLSA and Sigstore software supply chain security architecture covers provenance and signing; this article focuses on the inventory and exploitability layers that sit beside it.
A note on terminology. An SBOM describes components and relationships. A VEX document (or VEX statement) asserts the exploitability status of specific vulnerabilities in specific products. Reachability analysis is a technique, usually static call-graph analysis, that estimates whether vulnerable code can be executed from the application’s entry points. Attestation is a signed statement about an artefact, binding a claim (such as “this is the SBOM for this image digest”) to a cryptographic identity.
The SBOM and VEX Reference Architecture
In short: an SBOM VEX pipeline generates an SBOM at build time, signs it as an attestation bound to the artefact digest, matches it against vulnerability feeds, then applies VEX statements from suppliers and your own analysts to suppress non-exploitable findings. What remains is a small, evidence-backed triage queue instead of a raw scanner dump.

Figure 1: Reference SBOM VEX pipeline. The SBOM is generated at build, attested against the image digest, matched to vulnerability feeds, then filtered by VEX statements before reaching a human triage queue.
The diagram shows the data flow rather than any single product. Source code and lockfiles feed the build; the build emits an artefact and an SBOM; a signing step produces an in-toto attestation stored next to the artefact in a registry; a matcher joins SBOM components with vulnerability feeds; and a VEX layer, authored by both suppliers and your own team, decides which matches survive into the human queue. Each stage has a distinct failure mode, covered later.
Generate at build, not at scan time
The single most important design choice is where the SBOM is produced. Scanning a finished container image with a tool such as Syft or Trivy reconstructs the inventory from what is on disk: package manager databases (dpkg, rpm, apk), language lockfiles, and file-level cataloguers. That is useful and often the only option for third-party images. But it is a reconstruction.
Generating during the build, from the build system’s own dependency resolution, captures knowledge the finished image has lost: which dependencies were test-only, which were statically linked into a binary, which version the resolver actually selected after conflict mediation. CycloneDX’s Maven, Gradle and npm plugins, and the multi-language cdxgen generator, work this way. Syft and Trivy can also run in a pipeline stage against source directories. The pragmatic pattern is both: a build-time SBOM as the authoritative record, and an image-scan SBOM as a cross-check that catches what the build system did not know about, such as a base-image package or a binary copied in by a Dockerfile line.
A useful rule: if two SBOMs for the same digest disagree materially, treat the disagreement as a finding. It usually means a dependency entered the image outside the declared build graph.
Bind the SBOM to the artefact with an attestation
An unsigned SBOM file sitting in a wiki is a claim with no anchor. The robust pattern stores the SBOM as an in-toto attestation: a signed envelope whose subject is the artefact’s SHA-256 digest and whose predicate is the SBOM document, with a predicate type such as the CycloneDX or SPDX predicate URIs. Cosign from the Sigstore project can create and verify these (cosign attest --type cyclonedx or --type spdxjson), and with keyless signing the certificate identity records which CI workflow produced the claim. The attestation is pushed to the same OCI registry as the image, discoverable by digest.
This binding matters for triage because it makes the SBOM queryable by digest at the moment a new CVE lands. When a critical advisory drops, you do not rescan the fleet; you query the stored SBOMs for the affected package URL and get back the list of digests, and from those the deployed workloads. Rescanning is minutes to hours per image; a query against an SBOM index is seconds.
Join with feeds, then apply VEX
The matcher (Grype, Trivy, Dependency-Track, OSV-Scanner and commercial equivalents) joins the SBOM’s component identifiers with vulnerability data. Dependency-Track deserves a mention as the open-source platform built around CycloneDX ingestion: it stores SBOMs per project, continuously re-evaluates them as feeds update, and can ingest VEX to set analysis states. The key architectural point is continuous evaluation. The SBOM is a fixed fact about a build; the vulnerability landscape changes daily. A stored SBOM re-matched nightly finds vulnerabilities disclosed after release without rebuilding anything.
VEX is applied after matching. For each (component, vulnerability) pair, the engine looks up statements. A supplier’s not_affected statement with a valid justification removes the finding from the actionable list but keeps it in the audit trail. An affected statement raises priority. A fixed statement tells you which version resolves it. No statement means the finding stays, which is the correct conservative default.
Why this beats “scan and triage by CVSS”
Prioritising by Common Vulnerability Scoring System (CVSS) base score alone is a known poor filter: base scores describe worst-case severity of the flaw in the abstract, not exposure in your deployment. Adding the Exploit Prediction Scoring System (EPSS) probability and the CISA Known Exploited Vulnerabilities (KEV) catalogue improves ranking considerably. VEX adds a different and orthogonal signal: product-specific applicability asserted by the party who knows the product best. In practice the strongest queue combines all four: VEX status removes the impossible, KEV and EPSS rank the plausible, and CVSS plus asset criticality break ties.
CycloneDX vs SPDX: Data Model, Scope and Tooling

Figure 2: How CycloneDX and SPDX compare. CycloneDX embeds components, services, vulnerabilities and VEX in one BOM; SPDX 3 models everything as a graph of elements grouped into profiles.
Both formats can express the NTIA minimum elements, so the contest is about shape, scope and ecosystem.
CycloneDX: a BOM that grew outward
CycloneDX is organised around a single document, the BOM, that contains components, services, dependencies and compositions. It has first-class concepts for things beyond libraries: services and their data flows, machine-learning models (ML-BOM), hardware, and cryptographic assets (CBOM). The 1.6 release (April 2024) added CBOM and CycloneDX Attestations (CDXA), plus RFC 9116 security-contact references, and was submitted to become ECMA-424; the 1.7 release followed in October 2025 with provenance, citation and intellectual-property additions. Patch releases (1.7.1, 1.7.2) have since been schema-alignment fixes. Verify the current patch level on the specification repository before pinning a version in tooling.
Critically for this article, CycloneDX has a native vulnerabilities section. It can sit in the same document as the component inventory, or in a standalone VEX document that links to the SBOM via a BOM-Link URN. Each vulnerability entry carries an analysis object with a state (for example exploitable, in_triage, false_positive, not_affected, resolved, resolved_with_pedigree), a justification, a response (such as can_not_fix, will_not_fix, update, workaround_available), and free-text detail. Its affects array references components by bom-ref, which is how a VEX entry points at a specific component instance. Note that CycloneDX’s state vocabulary is richer and differently named than the OpenVEX and CSAF vocabularies; mapping between them is a real integration task.
SPDX: a graph with profiles
SPDX 2.3 (August 2022) is the version most tooling and most procurement documents still reference. It is a package-and-relationship model with rich licence expression support, file-level information, and multiple serialisations: tag-value, JSON, YAML, RDF and spreadsheet. Its strength is licence compliance depth: concluded versus declared licences, file-level copyright text, and relationship types such as DEPENDS_ON, CONTAINS and GENERATED_FROM.
SPDX 3.0, released in April 2024, restructures the model into a graph of elements with a JSON-LD serialisation and a set of profiles: Core, Software, Security, Licensing, Build, AI and Dataset, among others. The Security profile is where vulnerability and VEX-style assessment relationships live, and it supports expressing VEX-like statements natively. The Build profile can describe how an artefact was produced, which overlaps with SLSA provenance. The trade-off is adoption: version 3 is a larger conceptual jump than 2.3, and as of this writing, tooling coverage for SPDX 3 consumers is still catching up, so confirm that every tool in your chain reads the version you emit.
A practical decision matrix
| Criterion | CycloneDX | SPDX |
|---|---|---|
| Origin and emphasis | OWASP, security and supply chain first | Linux Foundation, licence compliance first |
| Standards status | ECMA-424 (based on 1.6) | ISO/IEC 5962:2021 (2.x line); 3.0 released 2024 |
| Native VEX in the same format | Yes, vulnerabilities with analysis |
Via Security profile in 3.0; weaker in 2.x |
| Beyond software (ML, hardware, crypto) | ML-BOM, HBOM, CBOM | AI and Dataset profiles in 3.0 |
| Licence-compliance depth | Good, SPDX expressions supported | Strongest, file-level detail |
| Serialisations | JSON, XML, Protobuf | JSON, YAML, tag-value, RDF, JSON-LD (3.0) |
| Typical consumers | Dependency-Track, security platforms | Legal and compliance teams, OSS foundations, procurement |
The honest summary: if your primary goal is vulnerability triage, CycloneDX gives you the shortest path because SBOM, vulnerabilities and VEX live in one toolchain. If you must satisfy customers or auditors whose templates say SPDX, emit SPDX as well. Most generators produce both from the same scan, and the cost of emitting two files is trivial compared with the cost of a procurement blocker.
The fork in the road is VEX, not inventory
For inventory fields alone, the formats are largely interchangeable and converters exist. The meaningful divergence is in how exploitability is expressed and consumed. A team that standardises on CycloneDX for the SBOM may still publish VEX as OpenVEX or CSAF because the consumer wants that format. That is the topic of the next section, and our deeper treatment of VEX with CSAF and OpenVEX for SBOM triage automation goes into the automation mechanics.
VEX Statuses, Formats and the Triage Walk-through
A VEX statement answers one question for one product: “Is this vulnerability exploitable here?” The CISA “Minimum Requirements for VEX” (April 2023) describes what any VEX document must carry regardless of format: document metadata, a product identifier, a vulnerability identifier, and a status. The four status values common across the major formats are:
- not_affected: the product contains the component but the vulnerability cannot be exploited; a justification is required.
- affected: the product is vulnerable; the supplier should add remediation guidance.
- fixed: the named product version contains the fix.
- under_investigation: the supplier is still assessing.
The OpenVEX specification defines a fixed set of justifications for not_affected: 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. The CSAF VEX profile uses known_not_affected, known_affected, fixed and under_investigation in its product-status object, with flags carrying the justification labels. CycloneDX uses its own analysis.state and analysis.justification vocabulary, as shown earlier. The three are semantically close but not identical, so a translation layer in your pipeline is not optional if you consume statements from several suppliers.
The three VEX formats compared
| Aspect | OpenVEX | CSAF 2.0 VEX profile | CycloneDX VEX |
|---|---|---|---|
| Steward | OpenVEX project, originated with Chainguard | OASIS (standard since November 2022) | OWASP CycloneDX / Ecma |
| Weight | Minimal JSON-LD, easy to hand-write | Heavy, full advisory structure | Medium, lives inside or beside the BOM |
| Product identification | Package URLs, hashes, OCI digests | Product tree with CPE, PURL, hashes | bom-ref into the SBOM |
| Best for | Image and library suppliers, CI-generated statements | Vendors with formal disclosure programmes, CERTs | Teams already on CycloneDX tooling |
| Signing story | Sigstore-friendly | Detached signatures, distribution via provider metadata | Attach as attestation |
The practical split: OpenVEX is the easiest to generate in CI and attach to an image; CSAF is the right format for a vendor publishing advisories to many customers and scanners; CycloneDX VEX is the lowest-friction choice when your own platform already ingests CycloneDX.
Worked example: from 412 findings to a short queue
The numbers below are illustrative, not measured from a real system, but the shape of the reduction is typical of what teams describe. Take a Java service image with 412 raw findings from a matcher. Applying filters in a sensible order:
- Duplicate and alias collapse. The same flaw appears as a CVE and a GHSA identifier across two feeds. Deduplicating on alias gives, say, 340 unique vulnerability-component pairs.
- Distribution-backport VEX. The base image vendor publishes statements saying 90 of those OS-package CVEs are fixed in the shipped package revision despite an old upstream version string. Down to 250.
- Component not present or code not present. Build-time analysis shows 70 findings sit in test-scope dependencies that never reach the runtime layer. Down to 180.
- Reachability. Static call-graph analysis marks 110 of the remaining library findings as having no call path from application entry points. After analyst review of a sample, these become
vulnerable_code_not_in_execute_pathstatements. Down to 70. - Exploit signals. Of 70, 4 are in CISA KEV or carry high EPSS. Those go to the top.
The queue went from 412 to 70 with 4 urgent. The critical discipline is that steps 2 to 4 are evidence-backed statements, not silent suppression. Each carries a justification, an author and a timestamp, so an auditor can see why a finding disappeared, and a later change (a new call path introduced by a refactor) can reverse it.

Figure 3: The triage funnel for a single image. Each stage removes findings with a recorded justification, leaving a short, ranked queue. Counts are illustrative.
The funnel is a mental model more than a fixed algorithm. The order matters because cheap, high-confidence filters (aliases, supplier statements) should run before expensive ones (reachability, human review).
Commands that make it concrete
The following sequence uses open-source tools as they exist at the time of writing; flag names change between releases, so check each tool’s help output before copying.
# 1. Generate a CycloneDX SBOM from a built image
syft registry.example.com/shop/api@sha256:abc123 -o cyclonedx-json=sbom.cdx.json
# 2. Attach it to the image as a signed attestation (keyless)
cosign attest --yes --type cyclonedx \
--predicate sbom.cdx.json registry.example.com/shop/api@sha256:abc123
# 3. Match against feeds, applying an OpenVEX document
trivy sbom sbom.cdx.json --vex api.openvex.json --format json -o findings.json
A minimal OpenVEX statement suppressing one finding looks like this:
{
"@context": "https://openvex.dev/ns/v0.2.0",
"@id": "https://example.com/vex/api-2026-001",
"author": "Platform Security Team",
"timestamp": "2026-10-15T06:00:00Z",
"version": 1,
"statements": [{
"vulnerability": { "name": "CVE-2025-00000" },
"products": [{ "@id": "pkg:oci/api@sha256:abc123" }],
"status": "not_affected",
"justification": "vulnerable_code_not_in_execute_path",
"impact_statement": "Affected parser class is never instantiated; verified by call-graph scan."
}]
}
The CVE identifier above is a placeholder. Tools such as vexctl (from the OpenVEX project) can create, merge and attach these documents, and the same file can be signed with Sigstore so consumers verify who made the claim.
Reachability: powerful, bounded
Reachability analysis asks whether a vulnerable function is on a call path from your code. For statically typed languages with clean call graphs it is quite effective; for reflection-heavy frameworks, dynamic dispatch, plugin loaders and interpreted languages it produces both false “unreachable” and false “reachable” verdicts. Treat tool output as evidence for a human VEX decision, not as an automatic not_affected. A good policy: auto-propose, require a named reviewer, and expire the statement when the dependency or the entry points change.

Figure 4: Decision flow for assigning a VEX status to one finding. The branches map directly onto the OpenVEX justifications.
Work through the flow in order. If the component is not in the shipped artefact, the answer is component_not_present. If it is, but the vulnerable function was compiled out or the affected platform branch is absent, it is vulnerable_code_not_present. If the code is present but no path reaches it, vulnerable_code_not_in_execute_path. If it is reachable but attacker input cannot influence it, vulnerable_code_cannot_be_controlled_by_adversary. If a mitigation such as a seccomp profile, a disabled feature flag or a WAF rule blocks the exploit, inline_mitigations_already_exist. Otherwise the status is affected, and the next question is whether a fixed version exists.
Who should author VEX?
Authority matters. A statement is only as trustworthy as the party making it. The supplier of a component is best placed to say whether a vulnerability in an upstream library affects their product, because they know how they use it. A downstream consumer can author VEX about their own deployment, for example that a service is not internet-exposed, but should not claim things about the supplier’s internals. Consumers should therefore verify the VEX signer’s identity (via Sigstore certificate identity or a trusted key) and treat unsigned statements from unknown parties as hints, not as suppression authority.
Policy gates and the registry as source of truth
Triage output should feed an enforcement point, not just a dashboard. In Kubernetes, admission controllers can require that an image carry a verified SBOM attestation, or block images whose attached findings include unmitigated KEV entries. If you already enforce signature checks, extending the same policy engine to verify attestation predicates is a small step; our comparison of Kubernetes policy-as-code with Kyverno and OPA Gatekeeper shows how each engine verifies image signatures and attestations at admission.
A workable gate has three tiers. The build gate fails a pipeline if no SBOM was produced or if the SBOM lacks the NTIA minimum fields. The release gate fails if any finding in KEV remains affected without an accepted exception. The runtime gate admits only images with a verified attestation whose signer matches the expected CI identity. Keeping the tiers separate stops one noisy rule from blocking everything, and it keeps exceptions auditable.
Storage and indexing at scale
At fleet scale, SBOMs become data. A mid-size organisation might hold tens of thousands of SBOMs, each from hundreds of kilobytes to several megabytes of JSON. The useful index is inverted: from package URL to the list of artefact digests containing it, plus a join from digest to deployed workloads. Dependency-Track maintains such a component index per project; alternatives include a graph database or a simple relational schema keyed by PURL. The design goal is answering “where is log4j-core below 2.17 running?” with a single query. Retain every SBOM version for as long as the artefact might still be deployed, and longer where regulation requires evidence of what was shipped.
Trade-offs, Gotchas, and What Goes Wrong
SBOM programmes tend to fail quietly, not loudly. These are the failure modes that recur.
Inaccurate SBOMs. An SBOM is only as good as its generator. Image-scan tools can miss statically linked dependencies, vendored source copied into a repo, binaries downloaded at runtime, and language-level components in stripped binaries. Studies and practitioner reports consistently find that different generators produce differing component lists for the same artefact; treat any single generator’s output as an estimate and cross-check critical systems with a second tool.
Identifier mismatch. Matching depends on the identifier. A missing or imprecise package URL, or a CPE that does not correspond to how the advisory names the product, yields false negatives, which are worse than false positives because they are invisible. Prefer package URLs for ecosystem packages and verify that your matcher uses the same identifier type as the advisory source.
VEX decay. A not_affected statement is true at a moment. A new feature, a dependency bump or a configuration change can make it false. Statements need expiry or re-validation triggers tied to the artefact digest; a statement that references a specific digest is naturally scoped, while one written against a version range can silently outlive its truth.
Suppression abuse. If teams are measured on a scanner’s finding count, the incentive is to write VEX statements to make the number fall. Guard against this by requiring a second reviewer for not_affected on high-severity items and by sampling statements for audit.
Format sprawl. Supporting CycloneDX, SPDX 2.3, SPDX 3, OpenVEX, CSAF and CycloneDX VEX all at once multiplies translation code and bug surface. Pick a canonical internal model (many teams pick CycloneDX plus OpenVEX), convert at the edges, and accept only what you can validate.
SBOM sharing and confidentiality. SBOMs reveal your dependency choices and versions, which an attacker can use. Decide who receives them: customers under contract, regulators on request, or public publication. Sign what you share, and do not assume that a public SBOM is risk-free.
False comfort. An SBOM does not prove the software is safe, does not detect malicious packages by itself, and does not cover runtime-loaded code. It is an inventory; its value is realised only through the matching, VEX and policy layers built on top.
Regulatory Context: Why Deadlines Make This Urgent
Two regimes shape SBOM adoption. In the United States, Executive Order 14028 (2021) started the federal software-transparency push, leading to the NTIA minimum elements and CISA’s secure software development attestation process for federal suppliers. US federal policy has been revised since; confirm the current requirements with CISA and OMB guidance before relying on any specific obligation.
In the European Union, the Cyber Resilience Act (Regulation (EU) 2024/2847) entered into force on 10 December 2024. Its manufacturer obligations to report actively exploited vulnerabilities and severe incidents begin to apply on 11 September 2026, and the main product requirements, including the Annex I essential requirements, apply from 11 December 2027. The Act requires manufacturers to identify and document the components in their products, including by drawing up a software bill of materials in a commonly used, machine-readable format covering at least top-level dependencies. Exact format expectations are being elaborated through guidance and technical standards, so treat format choice as something to validate against the final harmonised standards rather than assume. The reporting clock matters for VEX too: a fast, accurate statement about whether your product is affected is exactly what a 24-hour early warning process needs. This is general information, not legal advice.
Practical Recommendations
Start with the smallest slice that produces value, and add layers only when the previous one is stable.
First, generate a CycloneDX SBOM at build time for every release artefact, and an SPDX one if any customer demands it. Validate both against the NTIA minimum fields in CI. Second, sign and attach the SBOM as an attestation bound to the image digest; store a copy in an SBOM platform such as Dependency-Track for continuous matching. Third, consume supplier VEX where available (distribution vendors, major base-image publishers) before building your own. Fourth, author your own VEX in OpenVEX or CycloneDX for the findings that recur, with a reviewer, a justification and an expiry. Fifth, rank the residual queue with KEV, EPSS and asset criticality, and enforce a policy gate at admission.
- [ ] SBOM generated at build and cross-checked by an image-scan SBOM
- [ ] SBOM signed as an in-toto attestation bound to the digest
- [ ] SBOMs indexed by package URL for “where is X running” queries
- [ ] Nightly re-matching against vulnerability feeds
- [ ] VEX statements carry justification, author, timestamp and expiry trigger
- [ ] Second-reviewer rule for
not_affectedon high severity - [ ] Admission policy verifies attestation signer identity
- [ ] A translation layer between VEX vocabularies is tested
- [ ] Retention policy for SBOMs matches artefact lifetime
Frequently Asked Questions
What is the difference between an SBOM and VEX?
An SBOM lists the components and relationships inside a piece of software, answering “what is in it?”. VEX is a separate assertion about specific vulnerabilities, answering “does this vulnerability actually affect this product?”. The SBOM is relatively stable per build; VEX statements change as new vulnerabilities are disclosed and analysed. Together they turn a raw match list into a prioritised, evidence-backed queue, because VEX can mark matched findings as not affected, fixed or under investigation.
Should I choose CycloneDX or SPDX?
If vulnerability management is the main goal, CycloneDX is usually the shortest path because components, vulnerabilities and VEX share one format and strong tooling such as Dependency-Track. If licence compliance, legal review or customer templates drive requirements, SPDX is often expected. Most generators emit both, so many teams produce CycloneDX internally and SPDX on request. Check that each downstream tool supports the specific version you emit, especially for SPDX 3.
What are the VEX status values?
The commonly used values are not_affected, affected, fixed and under_investigation. A not_affected status needs a justification, such as component_not_present or vulnerable_code_not_in_execute_path in OpenVEX. CycloneDX uses its own analysis states, for example exploitable, in_triage, false_positive, not_affected and resolved, so a mapping layer is needed when you consume statements from suppliers using different formats.
Does an SBOM satisfy the EU Cyber Resilience Act?
Not on its own. The Act requires manufacturers to document components, including with an SBOM in a machine-readable format, but it also requires secure-by-design properties, vulnerability handling, update delivery, technical documentation and, from September 2026, reporting of actively exploited vulnerabilities. The SBOM is one input. Follow the evolving guidance and harmonised standards for format details, and seek qualified legal advice for your products.
How accurate are SBOMs?
Accuracy varies by ecosystem and generator. Build-time generation from the dependency resolver is generally more faithful than reconstructing from a finished image, and neither captures runtime-downloaded code or some statically linked components. Practitioners cross-check with a second tool and treat disagreements as findings. Treat an SBOM as a high-quality estimate that you continuously validate, not as ground truth.
Is reachability analysis enough to mark something not affected?
It is evidence, not proof. Static call-graph analysis can miss reflective calls, dynamic loading and framework-driven invocation, and can also over-approximate. Use it to propose VEX statements, require a human reviewer for important ones, and expire the statement when the code or dependencies change. Combine it with runtime evidence or configuration checks where the risk justifies the effort.
Further Reading
- SLSA and Sigstore software supply chain security architecture: provenance, signing and attestation layers that anchor your SBOM.
- VEX with CSAF and OpenVEX: SBOM triage automation: automating VEX consumption and publication.
- Kubernetes policy-as-code: Kyverno vs OPA Gatekeeper: enforcing attestation checks at admission.
- CycloneDX specification and SPDX specifications: the primary format documentation.
- NTIA, The Minimum Elements for an SBOM: the baseline data fields.
By Riju — about
