The Software Bill of Materials (SBOM) has gone from research artifact to regulatory obligation in less than five years. The Cyber Resilience Act (CRA, EU 2024/2847) mandates it for all products with digital elements; NIS2 makes it an implicit expectation for supply-chain security; DORA cites it as proof of ICT due diligence. This guide details how to produce, consume, and leverage a CycloneDX SBOM — the format that has emerged as the 2026 standard.
What is an SBOM?
An SBOM is a structured list of all software components that make up a product: open-source libraries, transitive dependencies, container images, licenses, suppliers. For a typical SaaS, that's 200 to 5,000 lines of direct and transitive dependencies.
Two dominant formats:
| Format | Publisher | Use case |
|---|---|---|
| CycloneDX | OWASP | Security-oriented, rich vulnerability metadata |
| SPDX | Linux Foundation / ISO 5962 | License-oriented, adopted by legal teams |
The CRA does not explicitly mandate a format, but the European Commission implementing rules (in progress in 2026) are converging on CycloneDX JSON for standardization.
Why it's mandatory under CRA
Article 14.1 of Regulation (EU) 2024/2847 requires manufacturers to:
"...identify and document vulnerabilities and components contained in the product, including by drawing up a software bill of materials in a commonly used, machine-readable format..."
Concretely, this means:
- SBOM available for each marketed version of a PDE
- Kept up to date on each new version or patch
- Machine-readable (structured JSON or XML)
- Accessible to market surveillance authorities on request (15 business days)
NIS2 entities (under Art. 21.2.e on acquisition security) increasingly require SBOMs from critical suppliers as contractual attachments.
For a deep dive on scope, see our CRA guide: 8 supplier contract clauses.
Structure of a CycloneDX SBOM
A minimalist CycloneDX JSON file looks like this:
{
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"version": 1,
"serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
"metadata": {
"timestamp": "2026-04-18T10:00:00Z",
"component": {
"type": "application",
"name": "MyProduct",
"version": "2.3.1"
}
},
"components": [
{
"type": "library",
"name": "lodash",
"version": "4.17.21",
"purl": "pkg:npm/lodash@4.17.21",
"licenses": [{ "license": { "id": "MIT" } }]
}
]
}
Critical fields for CRA compliance:
purl(Package URL) — universal identifier of a component, essential for CVE cross-referencinglicenses— for open-source compliance and legal traceabilityhashes— cryptographic integrity of the component (recommended)supplier— the entity that produced the component, useful for supply-chain cascade
Generate an SBOM automatically
Node.js / JavaScript
npm install --save-dev @cyclonedx/cyclonedx-npm
npx @cyclonedx/cyclonedx-npm --output-format JSON --output-file sbom.json
Python
pip install cyclonedx-bom
cyclonedx-py -e -o sbom.json
Docker containers
syft packages docker:myimage:latest -o cyclonedx-json > sbom.json
Java / Maven
<plugin>
<groupId>org.cyclonedx</groupId>
<artifactId>cyclonedx-maven-plugin</artifactId>
<version>2.7.11</version>
</plugin>
Best practice: generate the SBOM in the CI/CD pipeline at every release build. Store it alongside versioned artifacts (Git tag + SBOM = reproducibility).
Cross-reference with CVE databases
A raw SBOM only has value if cross-referenced with known vulnerabilities. Three sources to consume:
| Source | Coverage | Latency |
|---|---|---|
| NVD (NIST) | Officially published CVEs | 2-14 days |
| GitHub Security Advisories (GHSA) | Including ecosystem-specific vulnerabilities (npm, PyPI, etc.) | Hours |
| OSV.dev (Google) | Unified aggregator, recommended | Real-time |
For each purl component, query one of these databases and retrieve the list of applicable CVEs with their CVSS score. Automatable via public APIs — OSV example:
curl -X POST https://api.osv.dev/v1/query \
-d '{"package":{"purl":"pkg:npm/lodash@4.17.21"}}'
In ResiPlan, the SBOM module performs this cross-referencing automatically and triggers alerts in the CRA Dashboard when a new critical CVE affects a component of your registered products.
Receive SBOMs from your suppliers
If you are an integrator (embedding third-party products in your own SaaS), you must require an SBOM from every critical supplier. Sample contract clause:
"The Supplier shall provide an SBOM in CycloneDX or SPDX format, updated at every delivered version, covering all software components including open-source and transitive dependencies."
See our complete guide to the 8 CRA clauses for drafting.
Concrete operational benefits:
- Visibility on the supply chain (who uses what)
- Rapid response to zero-days affecting a common component (Log4Shell 2021 type)
- Negotiation of security support with objective data
- Audit ready for NIS2 / CRA authorities
Distribute your SBOM to customers
Three modalities depending on confidentiality:
1. Public SBOM (recommended for open-source and commercial SaaS)
Publish the SBOM in a public Git repo with each release:
https://github.com/myorg/myproduct/releases/download/v2.3.1/sbom.cdx.json
2. SBOM under agreement (confidential products)
Host on an authenticated secure portal (Vault, Artifactory). Controlled distribution under NDA.
3. SBOM on demand (critical or classified products)
Provide within 15 business days of each legitimate request (customer, authority). Traceability of each distribution.
The CRA does not prescribe a modality but requires the availability of information. ResiPlan lets you trace distributions and incoming requests.
Common pitfalls to avoid
1. "Surface" SBOM without transitive dependencies
An SBOM listing only direct dependencies misses 90% of the actual content. Ensure your generator descends on the whole tree (--include-transitive option depending on tools).
2. Outdated SBOM
An SBOM generated 6 months ago is false today. CI/CD automation mandatory + rotation at every release build.
3. Incompatible format
Generating CycloneDX XML when your customer expects JSON makes the file hard to ingest. Stabilize on CycloneDX JSON 1.5+ (or SPDX JSON).
4. Components without purl
Without Package URL, impossible to cross-reference automatically with CVE databases. All modern generators produce purls, but artisanal SBOMs often omit them.
5. No long-term tracking
Generate ≠ exploit. Without tooling to alert when a new CVE affects your portfolio, the SBOM remains a static artifact.
How ResiPlan operationalizes your SBOM
Our SBOM Management module includes:
- Drag-and-drop import CycloneDX + SPDX (JSON/XML)
- Automatic parsing of components, purls, licenses, hashes
- Continuous CVE cross-reference on each component with alerts
- Diff between versions of SBOMs (new component, version change)
- Supplier SBOM ingestion with normalization and traceability
- Global dashboard: X components, Y vulnerabilities, Z critical
- Client-ready export with sensitive components masked if needed
Combined with the PDE Registry, CVD, and Annex I modules of the CRA Compliance suite, you get an end-to-end view of your product security posture.