cyber witchery lab

sbom-diff: comparing software bills of materials

diff your sboms, catch surprises before they ship
cargo install sbom-diff

links: repo docs crates.io

sbom-diff compares software bills of materials across versions. it tells you what changed: new dependencies, removed packages, version bumps, license switches. the kind of things you want to know before cutting a release.

why

sboms are important, sometimes even mandatory for software supply chain security. but generating them is only half the story—you also need to understand what changed between builds. did a transitive dependency sneak in a license change? did someone vendor a new library without review?

most sbom tooling focuses on generation or vulnerability scanning. sbom-diff fills the gap between: given two sboms, what’s different? it also gives you knobs for gates, what’s allowed and forbidden, etc.

usage

basic comparison:

sbom-diff old.json new.json

output looks like:

summary: +3 added, -1 removed, 7 changed

+ lodash@4.17.21 (npm)
+ axios@1.6.0 (npm)
+ semver@7.5.4 (npm)
- moment@2.29.4 (npm)

~ express@4.18.2 → 4.19.0 (npm)
~ typescript@5.2.0 → 5.3.0 (npm)
  ...

markdown output for pr comments:

sbom-diff old.json new.json -o markdown

filter to specific change types:

sbom-diff old.json new.json --only version,license

fail the build if someone adds a gpl dependency:

sbom-diff old.json new.json --deny-license gpl-3.0-only

format support

sbom-diff reads cyclonedx and spdx json files. it normalizes both to a common internal representation before diffing, so you can compare across formats if needed1.

component matching uses package urls (purls) when available, falling back to name+ecosystem identity matching. this handles the common case where different tools generate slightly different sboms for the same codebase.

design choices

a few things that matter:

ci integration

the obvious use case is pr checks. generate an sbom in ci, compare it against the baseline from main, post the diff as a comment. the --deny-license flag lets you enforce license policy without a separate tool.

i’m using it in a github action that runs on every pr. catches dependency changes that would otherwise slip through unnoticed.


  1. comparing cyclonedx against spdx for the same project is a good way to find out how much your sbom generators disagree with each other.↩︎