SPDX vs CycloneDX: Choosing the Right SBOM Format for Your Software Supply Chain
A clear, practical guide comparing SPDX and CycloneDX — their strengths, tools, and use cases — so you can pick the SBOM format that fits your workflow.
.png)
Now that you know what an SBOM is, let’s dive in into the different formats of SBOMs you could encounter, and see which one is the more appropriate for your use case.
While there are less known and used SBOM formats*, there are two dominant standards: SPDX and CycloneDX. These standards have evolved into implementations of the NTIA (National Telecommunications and Information Administration) 's "minimum elements" plus some extensions.
SPDX (Software Package Data Exchange)
SPDX is a standard developed under the Linux Foundation Open Compliance Program.
SPDX is particularly strong in license compliance, offering detailed fields to capture complex licensing information.
It supports various file formats like RDF/XML, JSON, and YAML
Its current latest version is 3.0, many tools, such as the SPDX maven plugin still rely on 2.3 though.
Strength: Licensing
Tools to generate SPDX SBOMs
CycloneDX
CycloneDX is the other widely adopted SBOM standard, developed by the OWASP Foundation.
CycloneDX focuses on creating a security context for software components. It is designed to facilitate vulnerability identification and outdated dependency analysis.
The specification extends beyond software libraries to standards such as software as a service bill of materials (SaaSBOM), Vulnerability Exploitability Exchange (VEX), and more.
It supports various file formats like XML, JSON, and Protocol Buffers.
Its current latest version is 1.6.1, although many tools such as Paketo Buildpacks and the CycloneDX Maven plugin still rely on 1.6.
Strength: Vulnerability Identification
Tools to generate CycloneDX SBOMs
Comparison of SPDX and CycloneDX formats
Let’s take a dependency found in Spring PetClinic 2.7.18, the popular caching library ehcache (a transitive dependency in this context) and see how it’s represented in both formats (both JSON files were generated from their Maven plugins) - please note that some other tools could still analyze the same project but come up with different information (as described in the previous chapters, some tools work with a container image, some others with filesystems, etc.)
SPDX representation of the package:
1 {
2 "SPDXID": "SPDXRef--5a0de17c0",
3 "copyrightText": "UNSPECIFIED",
4 "description": "End-user ehcache3 jar artifact",
5 "downloadLocation": "NOASSERTION",
6 "externalRefs": [
7 {
8 "referenceCategory": "PACKAGE-MANAGER",
9 "referenceLocator": "pkg:maven/org.ehcache/ehcache@3.10.8",
10 "referenceType": "purl"
11 }
12 ],
13 "filesAnalyzed": false,
14 "homepage": "http://ehcache.org",
15 "licenseConcluded": "NOASSERTION",
16 "licenseDeclared": "Apache-2.0",
17 "name": "Ehcache",
18 "originator": "Organization:Terracotta Inc., a wholly-owned subsidiary of Software AG USA, Inc.",
19 "summary": "End-user ehcache3 jar artifact",
20 "versionInfo": "3.10.8"
21 },
CycloneDX representation of the package:
{
"type" : "library",
"bom-ref" : "pkg:maven/org.ehcache/ehcache@3.10.8?type=jar",
"publisher" : "Terracotta Inc., a wholly-owned subsidiary of Software AG USA, Inc.",
"group" : "org.ehcache",
"name" : "ehcache",
"version" : "3.10.8",
"description" : "End-user ehcache3 jar artifact",
"scope" : "required",
"hashes" : [
{
"alg" : "MD5",
"content" : "35f94bd99bae66088df39d8a45e73468"
},
{
"alg" : "SHA-1",
"content" : "f0d50ede46609db78413ca7f4250d348a597b101"
},
{
"alg" : "SHA-256",
"content" : "bed87f71d8cd25a8a4ef65f274cc58301f28929a01417d0bee8d73953dc30bac"
},
{
"alg" : "SHA-512",
"content" : "deeafba63b4ff08f26721aa9b8582c486d4a12ad3889c3deadb52ca86cd71212550ffd71f7cefc8e58543fd0114f48cc086ec3c173091ea7a5c2f99a3919893e"
},
{
"alg" : "SHA-384",
"content" : "30be38713902e6c68cf32cc9ef5cf0a384d0dcacbe5d32e7dbdd8483c2f7002cadc68005a50084f1b56386e456023fc6"
},
{
"alg" : "SHA3-384",
"content" : "e349f39ae5a621ef760f7de6fde8a35140cb2a004d05653c9340779469dd61b18a0b8310c2a01b82cc02839bff58b7f0"
},
{
"alg" : "SHA3-256",
"content" : "6808204bcd31027ce377ecf6ece07ae9a39e209524201064663693cf763d6d3c"
},
{
"alg" : "SHA3-512",
"content" : "e0c691bdcdcd98b349b409fc0a0b7851a90090d71492cf882104007cea9adf2905e6ab59ba62d3241d4eff929beaf92eef09e7450cf58897b07f60fa30092992"
}
],
"licenses" : [
{
"license" : {
"id" : "Apache-2.0"
}
}
],
"purl" : "pkg:maven/org.ehcache/ehcache@3.10.8?type=jar",
"externalReferences" : [
{
"type" : "website",
"url" : "http://ehcache.org"
},
{
"type" : "issue-tracker",
"url" : "https://github.com/ehcache/ehcache3/issues"
},
{
"type" : "vcs",
"url" : "https://github.com/ehcache/ehcache3"
}
]
},
Few remarks about those SBOM entries:
- Most of the data was recovered from the published pom (official web page URL, license, publisher)
- Both SBOMs describe the same essential component and share several overlapping attributes:
- Name & Version
- SPDX: "name": "Ehcache", "versionInfo": "3.10.8"
- CycloneDX: "name": "ehcache", "version": "3.10.8"
- Description / Summary
- SPDX: "description": "End-user ehcache3 jar artifact"
- CycloneDX: same text in "description".
- Homepage / Website
- SPDX: "homepage": "http://ehcache.org"
- CycloneDX: appears under "externalReferences": [{ "type": "website" … }].
- Publisher / Originator
- SPDX: "originator": "Organization:Terracotta Inc.…"
- CycloneDX: "publisher": "Terracotta Inc.…".
- License
- SPDX: "licenseDeclared": "Apache-2.0"
- CycloneDX: "licenses": [{ "license": { "id": "Apache-2.0" } }].
- Package URL (purl)
- SPDX: via externalRefs with referenceType: purl.
- CycloneDX: native "purl" field, also reused in "bom-ref".
- So both encapsulate: what it is, who makes it, what version, what license, where it lives, and its unique identifier.
- The purl is probably the most important information that identifies precisely what the component is; in our case, pkg:maven/org.ehcache/ehcache@3.10.8
- scheme: the scheme is always pkg, indicating a package URL
- type: the package type or ecosystem, such as npm, maven, pypi, nuget, go, etc.
- name:can be namespaced, here it’s org.ehcache/ehcache which is groupId/artifactId
- version: 3.10.8
- Qualifiers and subpath can optionally be added, for example the CycloneDX SBOM added the ?type=jar qualifier (as opposed to war or ear)
The Bottom Line
Which one should you opt for?
As you can see, the most important information is included in both formats so it’s probably not liability to choose one over the other (with that said, I do like the extensibility and frequent updates to CycloneDX…); so you should rather choose the tool that best suits your development lifecycle to export your SBOM.
Maven / Gradle centric? Choose one of the plugins.
CI/CD centric? Why not use syft and its github action
Made the switch to PaaS like workflow with buildpacks? Just rely on Paketo Buildpacks SBOM generation
Bought a fully fledged solution like BlackDuck or Snyk? No worries, they do support SBOM exports.
* What about the lesser known (and oftentimes deprecated) SBOM formats?
Open format BOMS
Paketo Buildpack specific format for example: only used in the context of older Paketo Buildpacks, before CycloneDX and SPDX became popular
Syft JSON: It’s the Syft SBOM generator too (syft CLI)l native format, but it’s mainly used by Syft internally to capture all the information available in both SPDX and CycloneDX formats
SWID (Software Identification Tags): an ISO standard, XML only, very rarely encountered, even if it’s still mentioned on NIST (National Institute of Standard and Technology) website.
Proprietary format BOMs
Black Duck, WhiteSource (Mend.io), JFrog Xray — but these don’t leave their ecosystems.
Links: What is a software build of materials by BlackDuck