A firmware SBOM diff compares the software bills of materials of two firmware releases, the pair NTIA's July 2021 minimum elements already call for, since every new build or release needs a new SBOM. It lists what changed between release N and N+1: components added, removed or upgraded, licence changes, the CVEs the release closed and the ones it brought in, and the VEX statements that still hold. That list is the evidence behind CRA technical documentation, FDA submissions for a device change, and release notes written from data instead of memory.
Key takeaways
- A firmware SBOM diff compares the software bills of materials of two firmware releases, the pair NTIA's July 2021 minimum elements already call for, since every new build or release needs a new SBOM.
- A firmware SBOM diff compares two component inventories, while binary diffing compares two sets of executable code.
- Regulators and customers ask what changed, and the SBOM pair is the only record that answers at component level.
- A release-to-release diff should report four kinds of component change and three kinds of vulnerability change.
What is a firmware SBOM diff, and how is it different from binary diffing?
A firmware SBOM diff compares two component inventories, while binary diffing compares two sets of executable code. The SBOM diff answers "which packages and versions changed"; binary diffing answers "which functions inside this binary changed".
The two methods sit at different depths and serve different readers:
| SBOM diff | Binary (patch) diffing | |
|---|---|---|
| Input | Two SBOMs (CycloneDX or SPDX) | Two unpacked firmware images |
| Unit of comparison | Component: name, version, licence, identifier | Function, basic block, instruction |
| Typical tools | CycloneDX CLI diff, an SBOM diff tool |
BinDiff, Diaphora, a disassembler |
| Question it answers | What did this release add, remove or upgrade? | What did a patch change inside one binary? |
| Who runs it | Release manager, product security, PSIRT | Reverse engineer, vulnerability researcher |
| How often | Every release | When a specific change needs explaining |
This guide covers the inventory side. When you need to know whether a vendor silently fixed a vulnerability inside a library whose version string did not move, that is the job of firmware diffing and patch analysis. The two meet in one place: an SBOM diff often tells you which component to point the binary diff at.
The SBOM itself has to come from the shipped image, not from a design document. How to build one from a binary, including when the ODM supplies no source, is covered in the firmware SBOM pillar guide.
Why compare the SBOMs of two firmware releases?
Regulators and customers ask what changed, and the SBOM pair is the only record that answers at component level. Release notes written by hand drift from what actually shipped; a diff of two SBOMs taken from the release images does not.
The NTIA minimum elements report sets the starting point under "Frequency": "If the software component is updated with a new build or release, a new SBOM must be created to reflect the new version of the software." Once you have one SBOM per release, the diff is the cheapest way to read them.
The Cyber Resilience Act adds several duties that a diff feeds directly. Annex I, Part II, point 1 requires manufacturers to identify and document components "including by drawing up a software bill of materials". Article 31(2) says the technical documentation "shall be continuously updated, where appropriate, at least during the support period", and Annex VII point 2(b) lists the SBOM inside that documentation. Annex I, Part II, point 4 requires manufacturers, once a security update is out, to "share and publicly disclose information about fixed vulnerabilities, including a description of the vulnerabilities". Point 2 of the same Part asks for security updates to be provided separately from functionality updates "where technically feasible", and a diff shows at a glance whether a security release also carried feature components.
For medical devices, the FDA premarket cybersecurity guidance issued on 3 February 2026 states that section 524B(b)(3) of the FD&C Act "requires manufacturers of cyber devices to provide an SBOM", and its section on modifications asks for an SBOM with a change submission as well. The same guidance asks, for each component, for its level of support and its end-of-support date, which a diff can track release by release.
| Driver | What it asks for | What the diff supplies |
|---|---|---|
| NTIA minimum elements (2021) | A new SBOM per build or release | The reason to compare N with N+1 |
| CRA Art. 31(2), Annex VII 2(b) | Technical documentation kept up to date, SBOM included | A dated record of each inventory change |
| CRA Annex I, Part II, point 4 | Disclosure of fixed vulnerabilities | The list of CVEs the release closed |
| FDA guidance, 3 February 2026 | SBOM for cyber devices, also in modification submissions; support status per component | Changed components and changed support status |
Sources: NTIA report p. 12; Regulation (EU) 2024/2847; FDA guidance sections V.A.4 and VII.D (all retrieved 13 November 2026). For a release checklist across the whole regulation, see the CRA checklist for device makers; the FDA side is covered in FDA premarket cybersecurity for medical devices.
What should a release-to-release SBOM diff report?
A release-to-release diff should report four kinds of component change and three kinds of vulnerability change. The component side is mechanical; the vulnerability side needs current CVE data and your own VEX records.
| Change | What to check | Why it matters |
|---|---|---|
| Component added | Supplier, licence, purl or CPE, support status | New attack surface, new licence terms, new CVE exposure |
| Component removed | Was it intended? Did a dependency drop it? | Closes CVEs; a missing component can also mean a broken build |
| Version changed | Upgrade or downgrade; upstream release or vendor backport | Upgrades close CVEs; a downgrade usually signals a stale SBOM |
| Licence changed | Old and new licence expression | A new copyleft licence brings source-sharing obligations |
| CVE closed | Which component change closed it | Feeds the fixed-vulnerability disclosure |
| CVE added | New component or new version in the affected range | Has to be triaged before release |
| VEX status to re-check | Statements made for the previous version | A "not affected" claim may stop being true |
Two reading rules save time. First, a version that sorts lower in the new SBOM is more often a sign that someone attached the wrong SBOM than a real downgrade; confirm the image hash before you investigate. Second, a component that disappears and reappears under a different name usually reflects a change of cataloguer or naming, not a change in the image. Identify components by purl where you can; our SBOM minimum elements guide explains which fields have to be present for this matching to work.
Keep the two SBOMs, the image hashes and the diff output together in the release record. Without the hashes, nobody can later prove which image the diff described.
How do you diff two SBOMs with open tools?
Generate one SBOM per release image with the same tool and settings, then compare them with a diff tool that reads your format. Using the same generator on both sides matters more than which generator you pick, because two tools name the same component differently.
Generate both SBOMs the same waySyft, maintained by Anchore on GitHub, writes CycloneDX or SPDX JSON with options such as -o cyclonedx-json. Run it, with the same version, over the unpacked root file system of each release. If your build system produces the SBOM, take both from the build system instead.Record the identity of each SBOMNote the firmware version and the image hash. In CycloneDX, each BOM carries a serial number and a version, and the BOM-Link specification on cyclonedx.org defines references of the form urn:cdx:serialNumber/version#bom-ref, so a later document can point at one component in one specific SBOM.Run the component diffThe CycloneDX CLI README documents cyclonedx diff <from-file> <to-file>, whose--component-versionsoption reports "component versions that have been added, removed or modified", with text or JSON output. The CLI is Apache-2.0 licensed; release v0.33.1 is dated 23 July 2026. It can also convert SPDX JSON 2.3 into CycloneDX first, with the README's warning that conversion between the two formats can lose some data.Re-match vulnerabilities for both SBOMsRun the same scanner, with the same database snapshot, over both files. Anchore's Grype README shows grype sbom:./sbom.jsonfor scanning an SBOM and lists KEV, EPSS and OpenVEX support. Comparing the two result sets gives you the closed and added CVEs.Review licencesRead every added component's licence and every licence change, not only the copyleft ones.
For a quick check without installing anything, the free SBOM diff tool compares two CycloneDX or SPDX 2.x JSON files in your browser, groups the result into added, removed, version-changed and licence-changed components, and exports Markdown or CSV for the change ticket. It matches components by purl and falls back to the name. When each purl carries its version, as generator output usually does, an upgrade appears as one removal plus one addition, so pair those rows by name. Its risk hints are fixed rules, not AI: they flag newly added copyleft or unlicensed components and likely downgrades.
A synthetic example shows the shape of a typical result. Between firmware 2.3.0 and 2.4.0, OpenSSL moves from 3.0.13 to a later 3.0 patch release, zlib moves from 1.2.13 to 1.3.1, an SSH server package is added, and a debugging utility is removed. That is four lines in the change log, each with a reason the release engineer can state in one sentence.
Which CVEs did the release close, and which did it add?
Compare the vulnerability matches of both SBOMs against the same data snapshot: a CVE matched on N and absent on N+1 was closed, a CVE matched only on N+1 was added. Using one snapshot for both sides keeps a database update from looking like a firmware change.
Each outcome has a natural home in a CSAF advisory. The OASIS CSAF 2.0 standard defines product status values per product version: fixed for versions that "contain a fix for the vulnerability", first_fixed for versions that "contain the first fix", last_affected for "the last versions in a release train known to be affected", and known_not_affected for versions "known not to be affected by the vulnerability".
| Diff outcome | Likely cause | Record it as |
|---|---|---|
| CVE on N, gone on N+1 | Component upgraded or removed | N+1 fixed or first_fixed; N last_affected |
| CVE on N and N+1 | Upgrade too small, or a backport the scanner cannot see | Still affected, or a VEX statement with evidence |
| CVE only on N+1 | New component or new version in the affected range | Triage before release |
| CVE gone, component unchanged | Data correction upstream, not a firmware change | No firmware change; check the snapshot |
Order the added CVEs the same way you order any finding: KEV first, then EPSS, then impact, as described in KEV and EPSS vulnerability prioritisation. A KEV entry that arrives with a new release is a reason to hold that release.
Do VEX statements carry over to the next firmware version?
Only after someone checks them again. A VEX statement is a claim about specific product versions, and a component upgrade, a changed build option or a new service can make a "not affected" claim false.
Carry a statement forward when the diff shows that the component, its version and the evidence behind the justification are unchanged. Re-check it when any of these appears in the diff:
- the component's version changed, even by a patch release;
- the build configuration changed, for example a kernel or BusyBox option that decided whether the vulnerable code is compiled in;
- a new component now calls the affected code, or a new network service exposes it;
- the statement relied on a mitigation that the new release changed.
Write the result per version. In CSAF that means listing the new product version in the right status group; in CycloneDX, a VEX entry can point at a component in a specific SBOM through BOM-Link. Format choice, product trees and publishing are covered in CSAF VEX for device makers.
Where can AI help with an SBOM diff?
AI is useful for turning a verified diff into readable text, and has no place in producing the diff or deciding what it means for exploitability. The comparison itself is deterministic and should be reproducible from the two files.
Good uses: drafting release-note lines from the diff rows ("zlib upgraded from 1.2.13 to 1.3.1"), grouping changes by subsystem, and summarising added CVEs per component with a citation for every sentence. The CycloneDX Common Release Notes Format gives such text a machine-readable home, with fields for the issues a release resolved, including security updates. Poor uses: guessing a missing version, deciding a CVE does not apply, or describing a change that no diff row supports.
SoftWSP follows the same split. The device firmware security service scans each firmware image on its own: unblob and Syft build a CycloneDX 1.6 SBOM, components are matched against NVD, CISA KEV, FIRST EPSS and CISA ICS advisories, a fixed ruleset scores them, and AI drafts the report text, which is rejected if any claim sentence lacks a cited record; an engineer reviews it before delivery. The platform has no built-in comparison between two images, so the release diff runs on two exported SBOMs, for example in the diff tool above. SoftWSP writes no VEX statements. How the triage pipeline works end to end, and where AI must not decide, is set out in AI-assisted SBOM and vulnerability triage for device firmware.
What does a release diff checklist look like?
One pass per release candidate, filed with the release record:
- Build the SBOM from the release image with the same generator and version as last time; store it with the image hash.
- Diff it against the SBOM of the last shipped release, not the last build.
- Explain every added, removed and version-changed component in one sentence; investigate any downgrade.
- Review every added licence and every licence change.
- Re-match both SBOMs against one vulnerability data snapshot; list closed and added CVEs.
- Triage added CVEs, KEV first; hold the release for unmitigated KEV entries.
- Re-check every VEX statement whose component or evidence changed; write statements for the new version.
- Update the technical documentation and the fixed-vulnerability disclosure from the same diff.
- Draft release notes from the diff rows and have an engineer approve the text.
Put this guide to work
Frequently asked questions
Is an SBOM diff the same as firmware binary diffing?
No. An SBOM diff compares two component inventories: which packages and libraries were added, removed or changed version or licence between two firmware releases. Binary diffing compares the executable code of two images function by function, with tools such as BinDiff, to find what a patch changed inside a binary, for example a silently fixed vulnerability. Run the SBOM diff on every release; use binary diffing when you need to know what changed inside one component.
Which open-source tool can diff two SBOMs?
The CycloneDX CLI, maintained by the CycloneDX project under the Apache 2.0 licence, has a diff command: "cyclonedx diff <from-file> <to-file>" with the option "--component-versions" reports component versions that were added, removed or modified. It reads CycloneDX XML, JSON and Protobuf and can convert SPDX JSON 2.3 first. SoftWSP's free SBOM diff tool compares two CycloneDX or SPDX 2.x JSON files in the browser and exports Markdown or CSV.
Why does an upgraded component show up as removed and added?
Because SBOM generators usually write the version into the package URL, for example pkg:generic/[email protected]. A diff that matches components by purl sees the old and the new purl as two different components, so an upgrade appears as one removal and one addition. Pair those rows by component name before you write the change log, and keep the purl of each side as the identifier.
Does a changed SBOM make a CRA substantial modification?
Not by itself. The Cyber Resilience Act defines a substantial modification as a change that affects compliance with the essential cybersecurity requirements or modifies the intended purpose, and recital 39 says a security update that fixes a known vulnerability without changing the intended purpose is not considered one. A diff that shows only patched libraries supports that reading; new components that add a network service or input deserve a closer assessment.
Can SoftWSP compare two firmware versions?
SoftWSP scans each firmware image on its own and delivers a CycloneDX SBOM with matched CVE, KEV and EPSS data and an engineer-reviewed report. The platform has no built-in release-to-release comparison: you compare two exported SBOMs, for example in the free SBOM diff tool, and our engineers can walk through the result with you. VEX decisions stay with your engineers.
Sources
- CycloneDX: CycloneDX CLI README, diff command (GitHub, release v0.33.1 of 23 July 2026, retrieved 13 November 2026)
- Anchore: Syft README, SBOM output formats (GitHub, retrieved 13 November 2026)
- Anchore: Grype README, scanning an SBOM, KEV, EPSS and OpenVEX (GitHub, retrieved 13 November 2026)
- NTIA: The Minimum Elements for a Software Bill of Materials (SBOM), 12 July 2021
- Regulation (EU) 2024/2847 (Cyber Resilience Act), Official Journal of the EU, 20 November 2024
- FDA: Cybersecurity in Medical Devices: Quality Management System Considerations and Content of Premarket Submissions, guidance issued 3 February 2026
- OASIS: Common Security Advisory Framework Version 2.0, OASIS Standard (18 November 2022), section 3.2.3.9 product status
- OWASP CycloneDX: BOM-Link capability (retrieved 13 November 2026)
- OWASP CycloneDX: Common Release Notes Format capability (retrieved 13 November 2026)
About this guide
SoftWSP Firmware Security Desk
Covers the SBOM cluster: 31 guides.

In this cluster
Questions about this page?
