EU Cyber Resilience Act and SBOMs for IoT Firmware: CycloneDX vs SPDX in Practice
A software bill of materials for firmware is easy to generate and hard to make true. Most embedded teams can produce a JSON file listing packages in an afternoon, yet that file usually omits the statically linked libraries, vendor SDK blobs and bootloader code that carry most of the real risk. The Cyber Resilience Act SBOM requirement turns this gap from a hygiene issue into a legal one: Regulation (EU) 2024/2847 obliges manufacturers of products with digital elements to document their components, and since 11 September 2026 it also obliges them to report actively exploited vulnerabilities on a clock measured in hours.
That second date matters now, because it applies to products already on the EU market, not only to new designs. A fleet of devices shipped in 2022 is in scope for reporting even though full conformity requirements arrive later. This post shows how to build an SBOM pipeline for IoT firmware that survives audit and incident response, how CycloneDX and SPDX differ in practice, and how VEX statements keep the noise manageable. Nothing here is legal advice.
What this covers: what the CRA actually requires of an SBOM, the BSI TR-03183-2 field checklist, a CycloneDX versus SPDX decision framework, generation tooling for Yocto, Zephyr and binary images, signing and attestation, the VEX workflow tied to Article 14 reporting, and the failure modes that sink real programs.
Context and Background
The Cyber Resilience Act entered into force in December 2024 and phases in. According to the regulation text and secondary analyses I checked for this post, the reporting obligations of Article 14 apply from 11 September 2026, the notification regime for conformity assessment bodies applied earlier in 2026, and the remaining obligations, including essential requirements, conformity assessment and CE marking, apply from 11 December 2027. Treat the exact application dates of the intermediate provisions as something to confirm against the Official Journal text with your counsel; the two dates that drive engineering work are the September 2026 and December 2027 ones.
The SBOM requirement itself sits in Annex I, Part II. Manufacturers must identify and document vulnerabilities and components contained in the product, including by drawing up a software bill of materials in a commonly used and machine-readable format covering at the very least the top-level dependencies. Two details deserve attention. The legal floor is top-level dependencies only, which is lower than what many customers and national guidelines expect. And the regulation does not name a format, so CycloneDX and SPDX are both defensible choices.
Annex VII places the SBOM inside the technical documentation that a manufacturer must keep, and Article 13 sets a support period of no less than five years unless the product lifetime is shorter. In practice this means the SBOM for firmware version 3.2 must remain retrievable and trustworthy long after the build servers that produced it are gone. Article 13 also requires due diligence on third-party components, which is where an SBOM becomes operational rather than archival: you cannot screen components you have not enumerated.
Germany’s Federal Office for Information Security (BSI) filled the format gap with Technical Guideline TR-03183 Part 2. Version 2.1.0, dated 20 August 2025, requires CycloneDX 1.6 or later or SPDX 3.0.1 or later for new SBOMs, and it adds mandatory fields beyond the NTIA minimum elements: hashes, licences, filenames and executable, archive and structured properties. It is a German guideline, not an EU harmonised standard, yet buyers and notified bodies are already using it as a reference, which makes it the practical benchmark. Our companion analysis of how the CRA maps against NIS2 and IEC 62443 for IoT and OT vendors covers the wider regulatory picture.
For the primary text, read Regulation (EU) 2024/2847 on EUR-Lex, and the BSI guideline from the BSI TR-03183 publication page.
The Reference Architecture: SBOM as a Lifecycle Control, Not a File
An SBOM that satisfies the Cyber Resilience Act is a controlled artifact produced by the release pipeline, bound to a specific firmware hash, stored for the support period, and consumed by a vulnerability process that can meet Article 14 deadlines. A static document generated once and attached to a datasheet satisfies none of that. The architecture below treats the SBOM as one node in a lifecycle.

Figure 1: How the SBOM connects Annex I vulnerability handling, Annex VII technical documentation and Article 14 reporting under the Cyber Resilience Act.
The figure shows two tracks that meet at conformity assessment. The design track covers secure-by-design requirements from Annex I Part I. The vulnerability track covers Annex I Part II: the SBOM, a coordinated vulnerability disclosure policy, security updates, and from 11 September 2026 the Article 14 reporting channel to the ENISA single reporting platform and onward to national CSIRTs. The SBOM feeds the technical file and the vulnerability track at once, which is why format and accuracy decisions made at build time echo through audits and incident response years later.
Principle one: the SBOM describes a deliverable, not a repository
BSI TR-03183-2 requires a separate SBOM for each software version, with a hash of the deployable component and the filename of the deliverable. That is a deliberate shift from source-centric inventories. Scanning a Git repository tells you what the developers declared; scanning the firmware image tells you what shipped. For IoT, the gap between the two is large because of static linking, vendored libraries, link-time garbage collection and board support packages that arrive as pre-built binaries.
The practical consequence is that you need two views and a reconciliation step. The build-system view (Yocto recipes, Zephyr modules, lockfiles) gives accurate names, versions and licences. The artifact view (a scan of the final image) catches what the build metadata missed. Disagreement between them is a finding, not a nuisance, and it is often the first honest picture of your supply chain.
Principle two: depth should exceed the legal floor
The regulation requires top-level dependencies at minimum. BSI TR-03183-2 asks for recursive dependency resolution at least up to and including the first component outside your scope of delivery, and for the completeness of each dependency list to be stated explicitly. A manufacturer that ships only top-level dependencies satisfies the letter of Annex I and then cannot answer the question that matters during an incident: does CVE-X affect us? Transitive dependencies are where most such answers live.
I would treat the legal floor as the design minimum for the legal file and the BSI depth as the engineering target. The cost difference between listing 40 top-level components and 400 transitive ones is almost nothing once the pipeline is automated; the benefit is that triage stops being manual archaeology.
Principle three: separate the stable from the volatile
SBOM content is relatively stable for a given firmware version, while vulnerability knowledge changes daily. The BSI guideline explicitly recommends keeping vulnerability data out of the SBOM and expressing it in separate documents such as VEX or CSAF files. This separation is also operationally convenient: you sign and archive the SBOM once, and you publish VEX statements as a living stream that points back to it by component identifier and product hash. We return to that workflow in the VEX section.
CycloneDX vs SPDX for Firmware: What Actually Differs
The short answer for a CRA programme is that either format can satisfy the regulation and the BSI guideline, so choose by consumer and toolchain rather than by ideology. CycloneDX, an OWASP-originated specification standardised as ECMA-424, is security-first and carries VEX natively. SPDX, an ISO/IEC standard in its 2.x line, is licence-first and has the deepest support in embedded build systems. Most IoT teams end up generating one natively and converting the other on demand.
Format lineage and current versions
CycloneDX 1.6 was ratified as ECMA-424, first edition, in June 2024. CycloneDX 1.7 was released on 21 October 2025, adding structured citations for provenance, patent assertions and expanded cryptographic bill of materials content; the project stated that ratification of 1.7 as ECMA-424 second edition was anticipated, and I could not confirm during research whether that completed, so treat it as unverified. The CycloneDX project reports more than 250 tools supporting its specifications.
SPDX 3.0 was a re-architecture rather than an increment. It moved to a graph model organised into profiles (core, software, security, build, licensing and others), serialised as JSON-LD, which is why BSI’s reference to SPDX 3.0.1 is not interchangeable with the long-standing 2.2 and 2.3 tag-value and JSON files that many tools still emit. That matters because the BSI minimum is SPDX 3.0.1; an SPDX 2.3 file from an older toolchain does not meet it for new SBOMs.
Practical differences that bite embedded teams
First, tooling reality. The Yocto Project generates SPDX through the create-spdx class by default, with SPDX 3.0 available via create-spdx-3.0 on the Scarthgap release but disabled by default according to the Yocto documentation. Zephyr’s west spdx command defaults to SPDX 2.3 and supports 2.2, 2.3, 3.0 and 3.1 through a --spdx-version option per the Zephyr documentation. For Linux-based firmware built with Yocto, SPDX is the path of least resistance. Application-level and container workloads tend to favour CycloneDX through tools like cdxgen and Syft.
Second, vulnerability context. CycloneDX embeds VEX-style analysis (states and justifications) inside the same schema or a companion document, so a single toolchain can carry component inventory and exploitability. SPDX 3.0 has a Security profile for equivalent statements, but ecosystem support is younger. If your triage team already lives in a vulnerability management platform, check which format it ingests losslessly before deciding.
Third, licence expressiveness. SPDX began as a licence-compliance format and its licence identifier list is the reference that BSI itself points to: licences must use SPDX identifiers or expressions, with LicenseRef- prefixes for anything not on the list. CycloneDX also uses SPDX licence identifiers, so this is rarely a differentiator for CRA, but it is for open-source licence audits of firmware that bundles GPL components.
Fourth, build provenance. SPDX 3.x introduces a Build profile for recording how an artifact was produced, which maps naturally to reproducible-build claims. CycloneDX covers some of the same ground with formulation data and, in 1.7, citations. Neither is a substitute for a signed provenance attestation, which we cover under signing.

Figure 3: Choosing a primary SBOM format by consumer, with BSI TR-03183-2 as the version floor.
A decision matrix for IoT teams
| Situation | Lean toward | Why |
|---|---|---|
| Yocto-based Linux gateway, licence audit is a main driver | SPDX | Native create-spdx; deepest recipe-level metadata |
| Zephyr or RTOS firmware, source and build files tracked | SPDX | west spdx records files, hashes and build relationships |
| Security team runs VEX and vulnerability management | CycloneDX | Native vulnerability analysis and wide scanner support |
| Mixed fleet: Linux gateways plus microcontroller nodes | One primary format plus conversion | Avoid two independent truths; validate conversions |
| Customer or notified body cites BSI TR-03183-2 | Either, at CycloneDX 1.6+ or SPDX 3.0.1+ | Version floor is the constraint, not the brand |
| Long-term archival for a 5+ year support period | Whichever you can validate and sign reproducibly | Prefer open, versioned schemas and archive the schema version used |
The last row deserves emphasis. Archival integrity depends on being able to parse and verify the file in 2031, so record the exact spec version, tool version and tool configuration alongside each SBOM. A file that cannot be validated against its schema later is not evidence.
The BSI TR-03183-2 Field Checklist
Because the CRA text is deliberately light on format, the BSI field list is the most concrete definition of “good” currently available. According to version 2.1.0, each component record must carry a creator (email or URL), name, version, filename, direct dependencies with completeness indicated, distribution licences, a SHA-512 hash of the deployable component, and three boolean properties: executable, archive and structured. The SBOM as a whole needs a creator and a timestamp, with UTC recommended.
Optional fields include the source code URI, a deployable-form URI, other unique identifiers such as PURL, CPE or SWID, original and effective licences, a source code hash, and the security.txt URL as defined in RFC 9116. The security.txt field is worth populating for CRA purposes because it points downstream parties to your vulnerability contact, which supports the coordinated disclosure policy Annex I Part II requires.
The three properties that confuse firmware teams
The executable, archive and structured properties are designed for a world of packages, but firmware images stress them. An executable is any file whose code is run directly or by a runtime, so a shell script counts. An archive is a combination of multiple components, regardless of compression. A structured archive carries metadata that lets the original components be recovered, as a container or zip does. An unstructured archive does not, and the BSI text names firmware images and statically linked binaries as examples.
This has a concrete implication. If a monolithic firmware blob is unstructured, you cannot decompose it from the outside, so the burden falls on you to decompose it from the inside at build time and record each embedded component explicitly. Treating the image as one opaque component with one hash satisfies the field list syntactically and fails the intent.
Licence handling and what to do when metadata is missing
BSI distinguishes original licences (assigned by the component’s creator), distribution licences (those that permit the licensee to use it) and the effective licence (the one you apply). For CRA purposes only the distribution licence field is mandatory, but a consistent record of all three simplifies disputes later. Where SPDX does not have an identifier, the guideline points to the ScanCode LicenseDB and the LicenseRef-<entity>- naming convention.
A frequent gap is vendor SDK code with no licence metadata at all. Do not leave the field blank. Record what the contract says, mark the source of the claim, and open a ticket with the vendor; an honest “unknown, requested on date” is more defensible than a silently empty field. Our post on secure IoT OTA firmware update architecture discusses how the signed update image and its SBOM should travel together.
Versioning discipline
The guideline states that if any component is altered, a new software version must be assigned to it, and that an SBOM is updated only when additional information on the included components arrives or errors are corrected. Read that carefully. It means you do not mutate an SBOM to reflect new vulnerabilities, because vulnerabilities live elsewhere. You issue a new SBOM revision for corrections and a new firmware version for any change in content. Transitional rules allow the immediately preceding guideline version for up to six months after a new one is released, and SBOMs compliant at delivery remain valid.
Generating the SBOM: A Firmware Pipeline
The goal is a pipeline that produces, on every release build, a validated and signed SBOM bound to the exact image hash. The figure below shows the shape: build-system sources and artifact scans are merged, normalised, checked against the field list, signed and published.

Figure 2: A firmware SBOM pipeline that merges build-system metadata with a scan of the final image, validates, signs and archives.
Build-system sources
For Yocto, enable SPDX generation through the distro configuration. The documented mechanism is the create-spdx class inherited via INHERIT_DISTRO, producing a compressed IMAGE-MACHINE.spdx.json under the image deploy directory, with further per-package files under tmp/deploy/spdx. Variables such as SPDX_INCLUDE_SOURCES and SPDX_ARCHIVE_SOURCES control whether source file descriptions and source archives are included. To use the SPDX 3.0 implementation on Scarthgap you swap the class:
# local.conf or distro conf (Scarthgap, per Yocto docs)
INHERIT_DISTRO:remove = "create-spdx"
INHERIT_DISTRO:append = " create-spdx-3.0"
SPDX_PRETTY = "1"
SPDX_INCLUDE_SOURCES = "1"
For Zephyr, the west spdx command reads the build’s CMake file-based API data and writes SPDX documents under build/spdx: separate documents for the application, the Zephyr tree, the built outputs and module dependencies. The --analyze-includes option adds header-level relationships at the cost of an extra compilation pass. Because the default is SPDX 2.3, pass --spdx-version explicitly if you need 3.0 or later to meet the BSI floor. Confirm the available flag set against your Zephyr release, since the command line has been changing and the older --init option is documented as deprecated.
Source and artifact scanners
Where the build system does not emit what you need, scanners fill the gap. cdxgen, an OWASP project, generates CycloneDX from source trees and supports several languages and package managers; its current documentation also lists SPDX 3.0.1 JSON-LD conversion, plus cdx-sign and cdx-verify utilities for JSON signatures. Syft from Anchore catalogues packages from container images and filesystems and emits CycloneDX JSON, SPDX JSON and in-toto based attestations; it pairs with Grype for matching against vulnerability data. Syft’s strength is the artifact view: pointing it at an extracted root filesystem of a firmware image finds packages the build metadata may not have declared.
# Artifact view: scan the extracted rootfs of a firmware image
syft dir:./rootfs -o cyclonedx-json=artifact-sbom.cdx.json
# Source view: dependencies declared in the application repo
cdxgen -o app-sbom.cdx.json .
Neither scanner will see a statically linked C library that was compiled into a stripped monolith with no embedded version string. For those, binary composition analysis tools or build-time recording are the only reliable options, and this is the single largest completeness risk in microcontroller firmware. I did not benchmark any of these tools for this post, and I would be sceptical of any published accuracy comparison that does not state its corpus.
Merge, normalise and validate
Merging is where most pipelines quietly lose information. The build-system SBOM gives authoritative names and licences; the scan gives presence evidence. A merge policy should state which source wins per field and should preserve conflicts as annotations rather than discarding them. Normalise identifiers to Package URL where an ecosystem exists, and keep CPE alongside because vulnerability databases such as NVD still key heavily on CPE.
Validation has two layers. Schema validation confirms the file parses against the declared specification version. Policy validation confirms the BSI field list is satisfied: every component has a SHA-512 hash, a filename, the three boolean properties, a licence expression and a dependency completeness statement. Write this as a CI gate that fails the release. Policy gates catch the quiet regressions, such as a new SDK drop that arrives without a licence, long before an auditor does.
Signing, Attestation and Retention
BSI says SBOMs should ideally be digitally signed so recipients can verify authenticity, and it recommends rather than mandates this. The CRA text does not require signatures on the SBOM either. I would still sign, because an unsigned SBOM handed to a customer or regulator is an assertion without a chain of custody, and because the same signing infrastructure you need for firmware update images already exists in your pipeline.
Three layers of integrity
The first layer is a signature on the SBOM document itself. cdxgen implements the JSON Signature Format for CycloneDX with support for component-level, multi-signature and sequential signature chains, driven by environment variables for algorithm and key material. For SPDX or for any file, a detached signature produced by your release signing service works equally well and is easier to audit.
The second layer is an attestation that binds the SBOM to a specific artifact digest. An in-toto style attestation carries a subject (the firmware image SHA-256 or SHA-512), a predicate type (the SBOM) and a signature. Syft can emit signed SBOM attestations in this family. The advantage is that verification answers a precise question: is this SBOM about this exact binary, produced by this identity? A plain signed document cannot say which image it describes unless the image hash is inside it and someone checks.
The third layer is provenance of the build itself, for example a SLSA-style provenance statement recording the builder, source revision and build inputs. This is optional for the CRA and valuable for credibility, particularly when a notified body or a large customer asks how you know the SBOM was generated from the shipped build.
Key management is the hard part
Signing is cheap; keeping the verification key meaningful for five years is not. Decide up front where the public verification keys are published, how key rotation is recorded, and how an old signature remains verifiable after rotation. A common failure is signing with an ephemeral CI identity and then losing the ability to trace which identity was authorised at release time. Archive the key identity, certificate chain and timestamp evidence with the SBOM.
Retention and retrieval
Annex VII technical documentation and the five-year support period under Article 13 imply retention at least for the support period. Store each SBOM, its signature, the VEX history, the exact tool versions and the firmware image hash in write-once storage keyed by product and firmware version. Test retrieval annually by picking a random old release and rebuilding the chain of verification. If you cannot do that exercise today, you cannot do it during an audit either. For the broader update path that delivers the signed image to the field, see our secure IoT OTA architecture guide.
VEX and Article 14: Turning Inventory into Decisions
An SBOM tells you what is inside. A VEX (Vulnerability Exploitability eXchange) statement tells you whether a vulnerability in a component actually affects your product. Without VEX, every CVE for a library present in your firmware looks like an emergency, and teams either drown or learn to ignore alerts. With VEX, you publish a reasoned status per product and vulnerability, and downstream parties inherit the analysis.
The status vocabulary
The OpenVEX specification defines four statuses: not_affected, affected, fixed and under_investigation. A not_affected statement must carry one of five justifications: component_not_present, vulnerable_code_not_present, vulnerable_code_not_in_execute_path, vulnerable_code_cannot_be_controlled_by_adversary or inline_mitigations_already_exist. A valid statement needs a vulnerability identifier, the product, the status and a timestamp. CycloneDX expresses the same idea through its vulnerability analysis states and justifications, and CSAF is the heavier advisory format used by many industrial vendors.
For firmware, vulnerable_code_not_in_execute_path is both the most useful and the most abused justification. Claiming it requires evidence such as build configuration showing the affected module is compiled out, or call-graph analysis of the linked image. Record the evidence reference in the statement. A blanket claim made without evidence is the VEX equivalent of an unsigned SBOM.
The Article 14 clock
Article 14 introduces three reporting stages for actively exploited vulnerabilities, and the clock starts when the manufacturer becomes aware. According to the regulation as summarised by several independent analyses, an early warning is due within 24 hours, a fuller notification within 72 hours, and a final report within 14 days after a corrective or mitigating measure is available. For severe incidents the final report is due within one month after the 72-hour notification. Reports go through the ENISA single reporting platform, which routes them to the coordinating CSIRT and to ENISA at once.
One of the secondary sources I read states that the platform went live on 11 September 2026 with a web interface requiring EU Login accounts and two-factor authentication, with manufacturers registering assigned representatives, and another noted no API at launch. I could not verify these operational details against an official ENISA page in this session, so check the portal documentation before building automation around them. Because reporting is manual at the outset, the work to prepare in advance is the content, not the connector.
An actively exploited vulnerability is defined in the regulation by reliable evidence that a malicious actor has exploited it in a system without the system owner’s permission. That is a higher bar than an exploit existing in the wild as a proof of concept, and your triage playbook should define who decides, using what evidence, within what time. The 24-hour clock does not leave room for a committee meeting.

Figure 4: Triage flow linking SBOM matches, VEX statements and the Article 14 reporting stages.
Scope and what is still ahead
Several independent analyses state that the Article 14 reporting duty applies to in-scope products regardless of when they were placed on the market, so legacy fleets are included, and that it continues after the support period ends. Open-source software stewards face a narrower regime, and reporting duties tied to upstream notification and public disclosure after fixes are described by some sources as applying from December 2027. Because secondary sources differ on details, I would not hard-code any of these into a compliance claim without reading the Article texts.
On penalties, sources I read disagree on the figure for Article 14 breaches: one reports a tier of up to 10 million euros or 2 percent of global turnover, another reports up to 15 million euros or 2.5 percent. I did not resolve this from the primary text in this session; Article 64 contains the authoritative tiers, so check it directly. Either way, the exposure is large enough to justify engineering the process.
A workable weekly and emergency loop
In steady state, run the SBOM store against vulnerability feeds continuously. For each new match, an analyst assigns a VEX status within a defined service level, publishing under_investigation early to show awareness. Matches with credible exploitation evidence switch to the emergency path: assemble the 24-hour early warning content, identify the coordinating CSIRT based on your main establishment, and prepare user notification. This is the point where the SBOM pays for itself: the question which products and firmware versions contain the component is answered by query in seconds.
The hard part is mapping a component finding to shipped products in the field. Maintain a registry linking each firmware version hash to the SBOM, and each device cohort to its firmware version. Where devices do not phone home, you can still bound exposure by sales and update records. Our guidance on Rust for embedded no_std firmware is relevant because memory-safe components shrink the class of vulnerabilities that ever reach this process.
Deeper Analysis: Where Firmware SBOMs Fail
Having a pipeline is not the same as having a trustworthy SBOM. The failure patterns below recur across embedded programmes and each has a mechanism worth understanding.
Static linking and vendored code
A C library compiled into the firmware as source, with its version string stripped, leaves no package-manager trace. Scanners that rely on package databases or version strings will not see it. The mitigation is process, not tooling: require every vendored dependency to be registered in a manifest with name, version, upstream URL and licence at the time it is added, and have CI fail on source directories that are not registered. Binary composition analysis can then serve as a cross-check rather than the primary source.
Vendor SDKs and binary blobs
Silicon vendors ship radio stacks, secure-element drivers and bootloaders as prebuilt binaries. You cannot scan inside what you cannot decompose, so your SBOM can only be as good as the vendor’s disclosure. Ask suppliers for their own SBOMs in a stated format and version, and record the dependency-completeness flag as incomplete when the vendor does not provide one. Article 13 due diligence on third-party components is the legal anchor for making that request. Some vendors publish tooling and advisories for their platforms, as one ESP32 vendor does with an SPDX-producing SBOM tool and a CVE-to-release dashboard, but coverage across vendors is uneven.
Identifier mismatches
Vulnerability matching depends on identifiers. A component recorded under a vendor-specific name may never match the CPE the NVD uses, producing false negatives that look like a clean bill of health. Record multiple identifiers per component (PURL, CPE, and the upstream project name) and treat zero matches for a well-known library as suspicious rather than reassuring.
Format conversion drift
Converting CycloneDX to SPDX or the reverse is lossy. Concepts such as dependency completeness, the executable and archive properties, and VEX analysis do not map one to one. If you must convert, validate the output against the BSI checklist after conversion rather than trusting the converter, and prefer converting from the richer source into the poorer target, not the reverse.
Timing and staleness
An SBOM generated at build time becomes stale the moment a component is patched in the field through a partial update. If your OTA system can update individual packages, the SBOM for the running device differs from the SBOM at release. Either forbid partial updates for regulated products, or regenerate and re-sign an SBOM for each distinct deployable state.
Trade-offs, Gotchas, and What Goes Wrong
The most common mistake is optimising for the artifact instead of the process. Teams generate a beautiful SBOM for the auditor and have no one who reads it when a CVE lands. The CRA does not reward the file; Article 14 punishes the missed deadline. Budget analyst time for triage before budgeting tool licences.
A second trap is false precision. An SBOM that lists 600 components with confident versions can be wrong in ways that look authoritative. State completeness explicitly, as BSI requires, and mark the parts you could not decompose. A smaller SBOM with honest gaps is more useful than a large one that implies certainty it lacks.
VEX introduces its own risks. Publishing not_affected creates a statement others rely on, and a wrong one is a liability. Require a second reviewer for justifications that depend on reachability, store the evidence, and set expiry so statements are re-examined when the component or configuration changes. Remember that a VEX statement is about a specific product version; it does not carry over to the next release automatically.
There is also genuine tension between transparency and security. Handing detailed SBOMs to customers helps them manage risk, and it also hands attackers a shopping list if the file leaks. Control distribution: share full SBOMs under agreement where appropriate, and publish a reduced view or VEX stream publicly. Whether the CRA obliges you to disclose the SBOM to users or only to market surveillance authorities on request is a legal question I did not resolve here; confirm with counsel.
Finally, regulatory instability is real. Implementing acts, harmonised standards and Commission guidance for the CRA were still being developed as of this writing, and the BSI guideline is national. Design for substitution: keep the format layer thin so that a future required profile or version can be produced by changing the exporter rather than redesigning the data model. Our overview of AI agent sandboxing with Firecracker, gVisor and Kata is not about firmware, but the isolation techniques it describes are relevant to building the CI environment that produces trusted SBOMs, since a compromised build runner can forge any attestation.
Practical Recommendations
Start from the date that is already in force. Reporting under Article 14 is live, so the first deliverable is not a perfect SBOM but a working path from “we learn a vulnerability is exploited” to “a report reaches the platform within 24 hours”. Name the decision owner, the backup, the evidence threshold and the coordinating CSIRT, and rehearse once with a fictional CVE.
Then build the inventory in the order that reduces risk fastest. Generate SBOMs from the build system you already have, add an artifact scan of the final image, reconcile, and treat discrepancies as a backlog. Pick one primary format, CycloneDX 1.6 or later or SPDX 3.0.1 or later, based on your toolchain and consumers, and keep conversion as an edge concern.
Make compliance mechanical. Put the BSI field checklist in CI as a failing gate, sign every release SBOM, bind it to the image digest, and archive it with tool versions for at least the support period. Ask every supplier for SBOMs and security contacts, and record what you did not receive.
- Define the Article 14 playbook and test the 24-hour path this quarter.
- Choose a primary format and pin the specification version in CI.
- Generate both a build-system SBOM and an image-scan SBOM per release; reconcile them.
- Enforce SHA-512, filename, licence, executable, archive, structured and completeness fields as a gate.
- Sign SBOMs, attach attestations to image digests, and archive for the support period.
- Maintain a firmware-hash to device-cohort registry for impact analysis.
- Publish VEX statements with justifications and evidence; set review expiry.
- Request SBOMs from silicon and SDK vendors; log gaps explicitly.
- Confirm penalties, disclosure obligations and dates with counsel against the Official Journal text.
Frequently Asked Questions
Does the Cyber Resilience Act require an SBOM?
Yes, indirectly and specifically. Annex I Part II requires manufacturers to identify and document components, including by drawing up a software bill of materials in a commonly used, machine-readable format covering at least top-level dependencies. Annex VII places it in the technical documentation. The regulation does not require you to publish it, and it does not name a format. National guidance such as BSI TR-03183-2 sets a higher depth and field standard that many buyers now expect.
Should I use CycloneDX or SPDX for IoT firmware?
Either can comply. Choose by toolchain and consumer: SPDX is native to Yocto and Zephyr and strong for licences, while CycloneDX is strong for security workflows and VEX. If you cite BSI TR-03183-2, use CycloneDX 1.6 or later or SPDX 3.0.1 or later. Avoid maintaining two independent sources of truth; generate one primary format and convert with validation.
When do the CRA vulnerability reporting duties start?
Article 14 reporting obligations apply from 11 September 2026, ahead of the main application date of 11 December 2027. Secondary analyses state they cover products already on the market. The stages are an early warning within 24 hours, a notification within 72 hours and a final report, with the timing depending on whether the case is an exploited vulnerability or a severe incident. Confirm details against the regulation text.
What is a VEX and do I need one?
A VEX statement declares whether a vulnerability affects a specific product, using statuses such as not affected, affected, fixed and under investigation, with a justification when not affected. The CRA does not name VEX, but it makes continuous vulnerability handling mandatory, and VEX is the efficient way to record and communicate those decisions. BSI recommends keeping vulnerability data in VEX or CSAF documents, separate from the SBOM.
Do SBOMs need to be digitally signed?
Not by the regulation text, and BSI recommends rather than requires it. Signing is still sensible: it proves integrity and origin, and binding the SBOM to a firmware image digest through an attestation shows which binary it describes. The harder obligation is long-term key management and retention so signatures remain verifiable throughout the support period of at least five years.
Which tools generate SBOMs for embedded Linux and RTOS firmware?
For Yocto, the built-in create-spdx class and its SPDX 3.0 variant. For Zephyr, west spdx. For source trees, cdxgen produces CycloneDX, and for container images, root filesystems and packaged artifacts, Syft emits CycloneDX or SPDX. None fully decomposes statically linked or stripped binaries, so combine build-time recording with image scans and vendor disclosures.
Further Reading
- EU CRA vs NIS2 vs IEC 62443: compliance mapping for IoT and OT vendors for how these regimes overlap.
- Secure IoT OTA firmware update architecture for the signed delivery path of the image your SBOM describes.
- Rust for embedded no_std firmware on microcontrollers for reducing memory-safety vulnerabilities at the source.
- AI agent sandboxes compared: Firecracker, gVisor and Kata for isolating the build environment that signs your artifacts.
- Regulation (EU) 2024/2847 on EUR-Lex, the primary legal text.
- BSI Technical Guideline TR-03183 Part 2, the SBOM requirements.
- OpenVEX specification for the status and justification vocabulary.
This post is technical analysis, not legal advice. Consult qualified counsel on your obligations under Regulation (EU) 2024/2847.
By Riju — about
