Safeguard
Developer Tools•

Diffing two SPDX SBOMs: which fields to compare and which to ignore?

Comparing two SPDX documents: ignore the Created time and document namespace, and compare package names, versions, identifiers and licenses. A field guide.

Safeguard Security Team
3 min read

When comparing two SPDX SBOMs, ignore document level fields that change on every run, namely the Created timestamp and the document namespace. Compare package names, versions, external identifiers, licenses, checksums and relationships. Those are the fields that describe the software rather than the file.

Document fields that always differ

The SPDX specification defines the Created field as the time the document was originally created, a required UTC timestamp. It defines the document namespace as a unique absolute URI, and states that if a document is updated and becomes a new version, a new URI shall be used. So by design these two values differ between any two documents, even identical content. Leave them out of a comparison.

The document identifier, SPDXRef-DOCUMENT, is fixed and will match anyway.

Fields that describe the software

FieldWhy compare itWhat a change suggests
Package nameBasic identityAddition, removal or rename
Package versionRelease levelUpdate or downgrade
External references such as package URLsStrong identity for matchingIdentity change, lookalike risk
License concluded and declaredObligationsRelicensing or a detection change
ChecksumsContent identityDifferent bytes, see below
Supplier or originatorProvenanceChange of publisher
RelationshipsStructureDifferent parent, new dependency path

Identifiers inside the file can change too

SPDX element identifiers such as package IDs are local to the document and are often generated sequentially. They can differ between runs while describing the same package. If your diff keys on them, you will see false changes. Match on the package URL when available, otherwise on name plus version.

Steps

  1. Parse both files rather than diffing text.
  2. Drop the Created time and document namespace.
  3. Build a map from package URL to package record for each file.
  4. Compare the maps: keys only in one side are additions or removals.
  5. For keys on both sides, compare version, license, checksum and supplier.
  6. Compare relationships last, since they change whenever structure changes.

Mixed formats

If one file is SPDX and the other CycloneDX, convert one first or compare through a common model. Differences in how formats express fields, such as scope or licenses, can produce false changes. Convert, then spot check a few entries by hand.

Interpreting license fields

Values such as NOASSERTION mean the generator could not determine a value. A move from a real license to NOASSERTION is a detection loss, not a relicensing. Treat it as a tooling difference and check the generator version.

Automate carefully

A script can do this in under a hundred lines. Test it on two identical runs and confirm it reports nothing. That test catches most of the noise sources above.

Safeguard generates SBOMs and scans dependencies, and its policies can act on license and component changes. A project overview is available on the free scan.

Quick check

Why does the SPDX namespace differ between two runs?

The specification requires a new unique URI for each new document version, so it always differs.

Should I match packages on SPDX element IDs?

No. They are local and can be regenerated. Match on package URL, or name plus version.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.