Firmware SBOM: how to build one when you only have the binary
A firmware SBOM (software bill of materials) lists every software component inside a device image: bootloader, kernel, libraries, daemons, vendor SDK modules and their versions. When you do not have the source code, you build it by binary analysis of the firmware image. Export it as CycloneDX or SPDX, pair it with VEX statements so only real issues remain, and keep one per release: the Cyber Resilience Act requires a machine-readable SBOM covering at least top-level dependencies.
Why device makers often have no source code
Most connected products are built along a chain: chip vendor → SDK or board support package → ODM → brand. The brand that sells the product under its name is the CRA “manufacturer”, but often receives only a finished binary. Other common reasons:
- the chip vendor’s SDK is frozen on an old kernel and toolchain;
- the original build environment is lost or the engineer has left;
- dozens of SKUs each ship a slightly different image.
You still need to know what is inside. Article 13(5) of the CRA requires due diligence on third-party components, and Annex I Part I (2)(a) requires shipping without known exploitable vulnerabilities.
How binary SBOM generation works
| Step | What happens | Typical output |
|---|---|---|
| 1. Unpack | Identify the image format, decompress, extract file systems (for example SquashFS, UBIFS, JFFS2, CPIO) and nested archives | Directory tree of the device root file system |
| 2. Inventory | Find executables, shared libraries, kernel modules, scripts, certificates and configuration files | File list with hashes |
| 3. Identify | Match files to components using package databases if present, version strings, symbols, build IDs and known signatures | Component name, version, supplier, confidence |
| 4. Relate | Link binaries to the libraries they load to show dependencies | Dependency graph |
| 5. Export | Write a CycloneDX or SPDX document with hashes and identifiers (CPE, purl) | SBOM file per firmware version |
| 6. Match vulnerabilities | Look up each component and version in vulnerability databases | Candidate CVE list |
| 7. Triage | Decide per CVE whether the product is actually affected | VEX statements |
Limits you should state openly
- Statically linked or stripped code is harder to identify; versions may be ranges.
- Vendor patches (backports) can fix a CVE without changing the version string, which produces false positives.
- Proprietary blobs may be identified only by supplier and hash.
Record a confidence level per component. A transparent, partial SBOM is more useful, and more defensible, than a “complete” one that is silently wrong.
CycloneDX vs SPDX for embedded firmware
| Aspect | CycloneDX | SPDX |
|---|---|---|
| Standardisation | Ecma International ECMA-424 (1st edition June 2024 = CycloneDX 1.6; 2nd edition December 2025 = CycloneDX 1.7) | ISO/IEC 5962:2021 = SPDX 2.2.1; SPDX 3.0 under development at ISO (to be confirmed) |
| Origin | OWASP, security-focused | Linux Foundation, licence-compliance-focused |
| Vulnerabilities and VEX | Native fields in the same document | Typically via separate VEX documents or SPDX 3 security profile |
| Hardware and firmware | Supports hardware and firmware component types | Package, file and snippet level detail |
| Formats | JSON, XML, Protocol Buffers | JSON, tag-value, RDF and others |
Both qualify as “commonly used and machine-readable” in the sense of CRA Annex I. Germany’s BSI technical guideline TR-03183-2 accepts both formats and asks for more depth than the CRA minimum (to be confirmed against the current BSI version). The Commission may also specify SBOM format and elements by implementing act (CRA Art. 13(24)); no such act is confirmed here (to be confirmed).
Practical advice: generate CycloneDX if your main use is vulnerability management and customer exchange; add SPDX if customers or licence audits ask for it. Converters exist, but check that hashes and identifiers survive conversion.
VEX: turning a CVE list into a decision
An old embedded Linux image can match hundreds of CVEs. Many are not exploitable because the vulnerable function is not compiled in, the service is disabled, or the attack path does not exist on the device. VEX records that decision in machine-readable form.
According to CISA’s VEX documents, each statement gives one product status:
| Status | Meaning |
|---|---|
| Not affected | The product is not affected; a justification is given |
| Affected | The product is affected; actions are recommended |
| Fixed | The product contains a fix |
| Under investigation | Not yet known; the document will be updated |
Justifications for “not affected” include: component not present, vulnerable code not present, vulnerable code cannot be controlled by an adversary, vulnerable code not in the execute path, and inline mitigations already exist.
VEX is also your evidence for Annex I Part I (2)(a): it shows you checked known vulnerabilities and why the remaining ones are not exploitable.
How an SBOM supports the CRA
| CRA requirement | How the SBOM helps |
|---|---|
| Annex I Part II (1): identify components, SBOM of top-level dependencies | The SBOM itself |
| Annex I Part I (2)(a): no known exploitable vulnerabilities | Basis for the pre-release vulnerability check |
| Annex I Part II (2): fix without delay | Tells you within minutes which products a new CVE hits |
| Article 14: 24-hour early warning | Lets you confirm affected versions fast; see CRA 24h reporting |
| Annex VII: technical documentation | The SBOM is part of the vulnerability-handling description; authorities can request it |
| Annex II (9): user information | If you choose to share the SBOM, tell users where to find it |
Machine builders face a similar duty under the Machinery Regulation: section 1.1.9 of Annex III requires the machine to identify its safety-relevant software at all times. See Machinery Regulation cybersecurity.
A workable process for firmware teams
- One SBOM per released build, stored with the image hash.
- Prefer build-time SBOMs where you control the build (Yocto, Buildroot and Zephyr can emit them), and use binary analysis to verify and to cover vendor blobs.
- Re-scan continuously: new CVEs appear daily for old components.
- Publish VEX with advisories so customers’ scanners show the same picture as you.
- Ask suppliers for SBOMs in your contracts, including chip-vendor SDKs and ODM firmware.
Softwsp builds SBOMs from firmware images without source code, triages vulnerabilities with VEX, and monitors each release afterwards: see device firmware security. For the regulation itself, start at the Cyber Resilience Act hub or the CRA checklist for device makers.
This guide is general information, not legal advice.
Frequently asked questions
Can you create an SBOM without source code?
Yes. Binary analysis unpacks the firmware image, identifies file systems, executables and libraries, and matches them to known components and versions using strings, symbols, signatures and package metadata. The result is less complete than a build-time SBOM and should state its confidence.
Should I use CycloneDX or SPDX for firmware?
Both are accepted machine-readable formats. CycloneDX is standardised as ECMA-424 and has built-in support for vulnerability and VEX data; SPDX 2.2.1 is published as ISO/IEC 5962:2021 and is strong on licensing. Pick the one your customers and tools consume; many teams produce both.
Does the Cyber Resilience Act require an SBOM?
Yes. Annex I Part II point (1) requires an SBOM in a commonly used, machine-readable format covering at least the top-level dependencies. It is part of the technical documentation, and market surveillance authorities can request it. Publishing it to users is optional.
What is VEX and why does it matter for firmware?
VEX (Vulnerability Exploitability eXchange) states whether a product is affected by a given vulnerability: not affected, affected, fixed or under investigation, with a justification for 'not affected'. It stops customers and scanners from flagging vulnerabilities in code your build does not use.