The EU Cyber Resilience Act requires manufacturers to generate and maintain a Software Bill of Materials for every product they ship. Article 13(5) specifies that the SBOM must be machine-readable and contain at minimum the NTIA minimum elements: supplier name, component name, version, unique identifiers, dependency relationships, author of the SBOM data, and timestamp.
For software products built with modern package managers, this is mostly a solved problem. For firmware, it is not. This guide explains how to generate a CycloneDX SBOM from a firmware binary, what the result should contain, and what reviewers look for when evaluating SBOM quality.
What Is CycloneDX?
CycloneDX is an open standard for describing software composition. It covers SBOMs, VEX documents, software as a service bill of materials (SaaSBOM), hardware bill of materials, and more. For firmware compliance purposes, the relevant format is CycloneDX SBOM version 1.5 or later.
The format is maintained by the OWASP Foundation and has been adopted as the preferred format by CISA, the EU’s ENISA, and most major compliance frameworks. CycloneDX’s advantage over SPDX for firmware is its tighter integration with VEX: both use the same component identifiers, so you can attach exploitability statements to SBOM components without format conversion.
What an SBOM Must Contain Under EU CRA
The NTIA minimum elements, referenced in EU CRA guidance, require:
Supplier name. The entity that created or distributed the component. For open-source components this is typically the project or foundation.
Component name. The name of the component as it would appear in a package registry or version control system.
Version. The specific version included. A range is not sufficient. The version must identify a specific release.
Other unique identifiers. Package URLs (purl) are the standard form: pkg:generic/[email protected] or pkg:deb/[email protected]. CPE (Common Platform Enumeration) identifiers are also acceptable and map directly to CVE database lookups.
Dependency relationships. Which components depend on which others. This is important for understanding blast radius when a component is found to be vulnerable.
Author of SBOM data. The entity that produced the SBOM document, which may differ from the product manufacturer.
Timestamp. When the SBOM was generated.
Beyond the minimum elements, a useful firmware SBOM should also include file paths (where in the firmware filesystem each component was found), hashes (to verify the component has not been modified), and license information.
Step 1: Extract the Firmware Filesystem
Before you can analyze what is in a firmware image, you need to extract it. Firmware files are typically compressed archives in one of several formats: SquashFS, JFFS2, CRAMFS, ext2/3/4, UBI volumes, ZIP-based formats, and others. The extraction process depends on the format.
For Squashfs:
binwalk -e firmware.bin
# or
unsquashfs filesystem.squashfs
For JFFS2:
jefferson -d output/ jffs2.img
The output is a directory tree containing all files from the firmware: binaries, configuration files, scripts, libraries, and any package manager databases if present.
Step 2: Identify Components from Binary Content
This is where firmware SBOM generation diverges from software SBOM generation. You cannot simply read a manifest file.
Several strategies combine to produce good component identification:
Package manager databases. Many embedded Linux systems retain their package manager database in the filesystem (/var/lib/dpkg/ for Debian-based, /lib/apk/db/ for Alpine, /var/lib/opkg/ for OpenWrt). If present, these give you clean component names and versions for everything installed through the package manager.
ELF string analysis. Most compiled binaries embed version strings. The strings command can extract them, and pattern matching against known version string formats (for example, OpenSSL 1.1.1w or BusyBox v1.33.1) identifies components in binaries that have no package database entry.
Symbol table matching. The exported and imported symbol names of a shared library are often distinctive enough to identify the library even without version strings. A library exporting EVP_EncryptInit_ex and SSL_CTX_new is OpenSSL.
Build ID matching. Some binaries include build IDs that can be matched against known builds in package repositories.
Each of these methods has limitations. For a production SBOM, you want to combine them and track confidence per component.
Step 3: Correlate CPE and Package URLs
For each identified component, you need identifiers that link to vulnerability databases. The two main identifier formats are:
Package URL (purl): pkg:generic/[email protected], pkg:deb/[email protected]. These are the preferred format for CycloneDX and are used by most modern vulnerability scanners.
CPE (Common Platform Enumeration): cpe:2.3:a:openssl:openssl:1.1.1w:*:*:*:*:*:*:*. These are used by the NVD and map directly to CVE records.
A complete SBOM should include both where possible. Purl is used by the tooling ecosystem; CPE is what the vulnerability databases use for CVE correlation.
Step 4: Build the CycloneDX Document
A minimal CycloneDX SBOM in JSON format looks like this:
{
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
"version": 1,
"metadata": {
"timestamp": "2026-06-15T10:30:00Z",
"tools": [{ "name": "FDIE", "version": "1.0" }],
"component": {
"type": "firmware",
"name": "MyDevice",
"version": "1.4.2",
"manufacturer": { "name": "My Company" }
}
},
"components": [
{
"type": "library",
"name": "openssl",
"version": "1.1.1w",
"purl": "pkg:generic/[email protected]",
"cpe": "cpe:2.3:a:openssl:openssl:1.1.1w:*:*:*:*:*:*:*",
"hashes": [
{
"alg": "SHA-256",
"content": "a4b489..."
}
],
"evidence": {
"occurrences": [
{ "location": "/usr/lib/libssl.so.1.1" }
]
}
}
]
}
In practice, a firmware image with hundreds of components produces a much larger document. The structure remains the same.
Step 5: Validate the Document
Before submitting an SBOM for compliance purposes, validate it. The CycloneDX project provides a JSON schema and a CLI validator:
cyclonedx validate --input-file sbom.json --input-format json --input-version v1_5
Common validation failures include missing required fields, invalid purl formats, and incorrect specVersion strings. Validation against the schema does not check that the component identification is accurate, but it does confirm the document is structurally correct.
What Auditors Check
When an auditor reviews a firmware SBOM for EU CRA compliance, common questions include:
Does it cover the full image, including vendor blobs? A common gap is pre-compiled vendor libraries that are not in the package manager database and not identified by the SBOM tool. Auditors increasingly ask specifically whether closed-source components are represented.
Are the versions specific? “openssl >= 1.0” is not acceptable. The SBOM must name a specific version for each component.
Is there a corresponding VEX document? An SBOM without VEX leaves the auditor with a list of CVEs and no information about which ones actually matter. SBOM and VEX together form the complete vulnerability disclosure documentation.
Is the SBOM versioned and dated? The SBOM for firmware v1.4.2 should be stored and accessible alongside that firmware release. An SBOM without a firmware version reference is difficult to audit.
Is it machine-readable? A PDF listing component names is not an SBOM. CycloneDX JSON or XML is.
How FDIE Automates This
FDIE handles extraction, component identification, purl and CPE generation, CycloneDX document assembly, and validation in a single pipeline. Upload a firmware image and the output includes a CycloneDX 1.5 SBOM, an SPDX 2.3 SBOM, and a CycloneDX VEX document. The component identification combines package database parsing, ELF string analysis, and binary signature matching. Each component entry includes file location, hash, confidence level, and both purl and CPE identifiers.

Every completed analysis exposes CycloneDX (CDX), SPDX, CBOM, and VEX exports directly from the report header.
SBOM generation is available on Pro and above.
Frequently Asked Questions
Does the EU CRA mandate CycloneDX specifically? No. The CRA requires a machine-readable format that contains the NTIA minimum elements. Both CycloneDX and SPDX satisfy this. CycloneDX is currently more widely used in the firmware security toolchain, but SPDX is equally valid.
How large does a firmware SBOM typically get? A typical embedded Linux firmware with a few hundred binaries produces an SBOM between 500KB and 5MB in JSON format. This is manageable to store and process, though most human reviewers will use tooling to query it rather than reading the raw file.
Does my SBOM need to include license information? The NTIA minimum elements do not require license information. For software supply chain and procurement use cases, licenses are important. For firmware security compliance under EU CRA, the security-relevant fields (name, version, CPE, hashes) are the priority.
What do I do when I cannot identify a component? Include it with the information you have: the file path, the SHA-256 hash, and whatever partial identification you can make. An unidentified component with a hash is better than an omission. An auditor who sees a hash without a name knows the component was observed and logged; a missing entry leaves no record at all.
Can I generate an SBOM from source rather than from the binary? Yes, but a source-derived SBOM will miss pre-compiled vendor blobs. For full compliance coverage, binary analysis is required to catch components that are not in your build recipes.