![]() |
VOOZH | about |
As organizations rely more on open-source and third-party components, software supply chain security has become more crucial than ever before. Software bills of materials (SBOMs) are a practical solution for gaining visibility into software components, identifying vulnerabilities, and ensuring license compliance. This Refcard covers the essential elements of SBOMs, their key formats, open-source tools for automating SBOM generation and attestation, and how to integrate SBOMs into development workflows.
Written By
With the growing reliance on third-party and open-source components, supply chain attacks have become more prominent. In order to circumvent this, software bills of materials (SBOMs) have been introduced. Simply put, an SBOM is a tool for identifying vulnerabilities and improving supply chain security. It helps organizations inventory all the software they use and quickly respond to security advisories affecting those components.
By the time you finish reading this Refcard, you will have a solid understanding of what an SBOM is, what it is made of, available formats, tools to generate it, and how it can be integrated into the software development lifecycle.
The formal definition of an SBOM, as the National Telecommunications and Information Administration (NTIA) puts it, "is a nested inventory for software, a list of ingredients that make up software components." SBOMs include details about the third-party libraries, modules, tools, dependencies, and runtime components that make up your application.
SBOMs provide the security transparency that organizations need to protect their software and applications. For example, using the information in an SBOM, security teams can assess the security risk associated with each package and take action depending on the criticality. Moreover, many organizations have an Open Source Program Office (OSPO) responsible for defining, implementing, and enforcing open source governance. The OSPO oversees the organization's use of open-source software and their contributions to open-source projects. Since SBOMs provide detailed inventories, the office can review these records from time to time, ensuring adherence to the governance policies.
The adoption of SBOMs has also grown dramatically in recent years. Initiatives like the European Union's Cyber Resilience Act and United States' National Institute of Standards and Technology (NIST) have expanded the use of SBOMs to other industries where software plays a major role, like automobile, medical, finance, and energy sectors.
To put this into context: Imagine an electrical vehicle or a power grid being compromised. Because the impact is high, regulations like the Cyber Resilience Act even grant authorities to reject any equipment that does not provide a compliant SBOM when necessary. As a result, early adoption of SBOM practices not only streamlines audits but also helps enforce license policies and improve incident response to emerging threats.
An SBOM should list all the components, open-source and third-party dependencies, along with their versions and licenses. In this section, we'll explore the key elements of an SBOM, examine different SBOM formats, and look at some examples of how to generate them.
The first thing to discuss is the schema. The NTIA mandates a minimum set of elements that must be included in an SBOM schema, along with optional fields that consumers of an SBOM can request if needed. Let's illustrate what these elements are with a simple example:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.software</groupId>
<artifactId>MyApp</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
</dependencies>
</project>
The above XML represents the pom file of a Maven project responsible for managing dependencies and their versions. The table below explains these elements in further detail:
Table 1
| Element | Description | Example |
| Supplier name |
Name of company that made the software |
Apache Software Foundation |
| Component name |
Name of software part |
MyApp |
| Component version |
Version of software being used |
1.0.0 |
| Other unique identifiers |
Ways to identify components and their versions uniquely (e.g., package URLs) |
pkg:maven/com.fasterxml.jackson.core/[email protected] (using package URL) |
| Dependency relationship |
Definition of how different components relate to each other |
|
| Author of SBOM data |
Name of person or group that created the list of an SBOM |
Apache Software Foundation |
| Timestamp |
Date and time of when the SBOM was created |
2025-05-10T12:00:00Z |
These elements are the minimum set of attributes that every SBOM must contain. Next, we will discuss the optional elements that further enhance the purpose and effectiveness of the bill of materials.
A cryptographic hash ensures that the component being used is the same as the intended component. Oftentimes in supply chain attacks, a piece of software may be tampered with to include malicious code and be distributed publicly. To prevent this, users must compare the hash of the downloaded software with the approved one. If they match, the software is considered safe to use. In other words, this is one way to ensure integrity in the software supply chain.
An SBOM can vary depending on where in the software development lifecycle it was built. For example, in the piece of code below, because the version is specified as latest, different versions of log4j could be downloaded at different times (on local box, during build). To address this variance, it is recommended to capture the lifecycle phase, whether it is source, build, or post build. The lifecycle phase acts as additional metadata that users can consider.
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>latest</version>
</dependency>
Sometimes, it is good to know whether a software dependency in use is a modified version of another base dependency. This is valuable information because if the original dependency has a known vulnerability, all of its modified versions may also be affected.
A perfect example of this can be forked dependencies. For instance, a company might use the Apache Commons Lang library but later fork the repository to create a custom version. Although the code is now maintained separately, any vulnerability in the original Commons Lang library could still impact the forked version. This is what we refer to as derivation, or descendancy dependencies. As a result, capturing the relationship information makes it easy for the security team to identify and mitigate risks inherited from shared code origins.
License information can help the organization protect itself from compliance issues. For instance, the components licensed under the General Public License (GPL) may require any software that uses it to be open sourced under the same license. Because this requirement can conflict with the company's business model, the organization may choose to avoid adopting such an open-source dependency.
An SBOM typically declares two types of dependencies: direct and transitive (also known as indirect):
Once the schema and requirements are established, the next step is to develop standardized SBOM formats, which enable seamless exchange between different systems to support automation, thereby promoting strong interoperability. Currently, there are three popular formats: Software Package Data Exchange, CycloneDX, and Software Identification Tag.
The Software Package Data Exchange (SPDX) is one of the most widely adopted SBOM standards and is formally recognized as an international standard under ISO/IEC 5962:2021 for software data exchange. It supports multiple representations, including XML, JSON, and plain text, making it flexible for different tooling and ecosystems. The example below demonstrates a plain text version of the SPDX format and includes all the minimum schema elements discussed earlier:
SPDXVersion: SPDX-2.3
DataLicense: CC0-1.0
DocumentNamespace: http://spdx.org/spdxpackages/io.dapr.spring_dapr-spring-parent-0.16.0-SNAPSHOT
DocumentName: dapr-spring-parent
SPDXID: SPDXRef-DOCUMENT
## Creation Information
Creator: Tool: spdx-maven-plugin
Created: 2025-05-10T23:11:23Z
LicenseListVersion: 3.26.0
## Relationships
Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef--4b3779bf0
RelationshipComment: <text></text>
## Package Information
PackageName: dapr-spring-parent
SPDXID: SPDXRef--4b3779bf0
PackageVersion: 0.16.0-SNAPSHOT
PrimaryPackagePurpose: INSTALL
PackageVerificationCode: da39a3ee5e6b4b0d3255bfef95601890afd80709
PackageHomePage: https://dapr.io/dapr-spring-parent
PackageLicenseConcluded: Apache-2.0
PackageLicenseDeclared: Apache-2.0
PackageSummary: <text>SDK extension for Spring and Spring Boot</text>
PackageDescription: <text>SDK extension for Spring and Spring Boot</text>
ExternalRef: PACKAGE-MANAGER purl pkg:maven/io.dapr.spring/[email protected]
## Relationships
Relationship: SPDXRef--4b3779bf0 DYNAMIC_LINK SPDXRef--10b0268e0
RelationshipComment: <text>Relationship based on Maven POM file dependency information</text>
## Package Information
PackageName: JUnit
SPDXID: SPDXRef--286550880
PackageVersion: 3.2.6
PackageOriginator: Organization:VMware, Inc.
PackageHomePage: https://spring.io/projects/spring-boot
PackageLicenseDeclared: Apache-2.0
PackageSummary: <text>Core starter, including auto-configuration support, logging and YAML</text>
PackageDescription: <text>Core starter, including auto-configuration support, logging and YAML</text>
ExternalRef: PACKAGE-MANAGER purl pkg:maven/org.springframework.boot/[email protected]
FilesAnalyzed: false
## Relationships
Relationship: SPDXRef--286550880 TEST_DEPENDENCY_OF SPDXRef--4b3779bf0
RelationshipComment: <text>Relationship created based on Maven POM information</text>
In this example:
SPDXVersion – Indicates the version of the SPDX format used. In this case, it is 2.3, although the latest version is 3.0, which was released in 2024.Creation Information – Since the SBOM was generated using a Maven plugin, the creator field includes Tool: spdx-maven-plugin, along with the timestamp and other optional license details.Package Information– Lists the dependencies used to build the dapr-spring-parentcomponent. It includes metadata such as the package name, version, and license.
PackageVerificationCode is used to verify the integrity of the package and ensure the user is downloading the correct version. This is the cryptographic hash that we discussed previously.ExternalRef includes a package URL (purl) that uniquely identifies the package and its version using a package manager reference.PackageLicenseDeclared specifies that the components are licensed under Apache 2.0, which is a permissive license with fewer usage restrictions.Relationships – Each package is assigned an SPDX Identifier (SPDXID). These identifiers are used to express relationships between packages. For example, TEST_DEPENDENCY_OF indicates that JUnit is a test dependency of the dapper-spring parent project.SPDX is particularly good at relationships. It offers a rich set of relationship types for describing how components are connected. Examples of other relationship types that SPDX supports include BUILD_DEPENDENCY_OF, DEPENDS_ON, and CONTAINED_BY.
CycloneDX (CDX) is another popular format developed by the Open Worldwide Application Security Project (OWASP). It especially shines at mapping dependency versions to vulnerabilities coming from vulnerability databases like CVE and CVSS. As a result, if the purpose of creating SBOMs is for identifying vulnerabilities, then CDX suits this use case better.
{
"bomFormat" : "CycloneDX",
"specVersion" : "1.6",
"serialNumber" : "urn:uuid:ed23acb5-17a8-3d29-a340-3f12db890b04",
"metadata" : {
"tools" : {
"components" : [
{
"type" : "library",
"author" : "OWASP Foundation",
"group" : "org.cyclonedx",
"name" : "cyclonedx-maven-plugin",
"version" : "2.9.1",
"description" : "CycloneDX Maven plugin",
"hashes" : [
{
"alg" : "MD5",
"content" : "9c7a565cf28cce58557d0c621c5ea4b1"
}
]
}
]
}
},
"components" : [
{
"type" : "library",
"bom-ref" : "pkg:maven/io.grpc/[email protected]?type=jar",
"group" : "io.grpc",
"name" : "grpc-netty-shaded",
"version" : "1.69.0",
"description" : "gRPC: Netty Shaded",
"hashes" : [
{
"alg" : "MD5",
"content" : "a72607f4fdca24e310ac1e91dc0010fb"
}
],
"licenses" : [
{
"license" : {
"id" : "Apache-2.0"
}
}
],
"purl" : "pkg:maven/io.grpc/[email protected]?type=jar",
}
],
"dependencies" : [
{
"ref" : "pkg:maven/io.grpc/[email protected]?type=jar",
"dependsOn" : [
"pkg:maven/io.grpc/[email protected]?type=jar",
"pkg:maven/io.grpc/[email protected]?type=jar",
]
}
]
}
Similar to SPDX, a CDX document includes metadata such as the following:
specVersion, which specifies the version of the CycloneDX format being used.metadata, which include plugin details used to generate the CDX document, as well as supplies other information like the tool name, version, and even the hashes of components.purl) uniquely identifies each element along with its version. dependsOn attribute, unlike SPDX, which supports a broader set of relationship types. license information is also included, specifying the license(s) associated with each component — in this case, Apache-2.0.Later, in the SBOM consumption section, we will look at how the CDX format can be used to detect vulnerabilities in the dependencies.
Software Identification (SWID) tags are primarily used to identify installed software, firmware, and products for inventory management. While they can describe the basic metadata and optional relationships, they do not fulfill the full requirements of an SBOM as they lack standardized support for transitive dependencies and complex dependency relationships.
There is also very limited tooling available for SWID tags. For example, while the swid-maven-plugin allows you to build a tag by manually specifying metadata, it does not automatically generate a tag from the existing project structure or dependency graph. So in short, SWID is more for inventory management.
To wrap things up, let's compare CycloneDX, SPDX, and SWID to better understand how they differ in scope and purpose.
Table 2
| Feature | SPDX | CDX | SWID |
| Origin and backing |
Linux Foundation |
OWASP Foundation |
ISO/IEC 19770-2 |
| Use case | Supply chain security, software license compliance and intellectual property management |
Supply chain security, vulnerability analysis |
IT asset and inventory management |
| Formats | Plain text, JSON, YAML, XML |
JSON, XML |
XML |
| Vulnerability data | Basic support (e.g., you can reference CVEs but not describe them) |
Built-in support for VEX (Vulnerability Exploitability eXchange) and VDR (Vulnerability Disclosure Report) |
No native support for vulnerability data |
| Industry adoption | Compliance-heavy organizations, OSS tools |
Security-first organizations, vendors |
Enterprises, government |
With the growing importance of supply chain security and SBOMs, a wide range of tools has emerged in this space over time. These tools can analyze everything from your software components to your infrastructure artifacts, such as Docker images and Kubernetes applications. Following are examples of open-source tools that can help automate the process of generating SBOMs for us.
SPDX offers a Maven plugin that can be integrated into the build phase. Below is an example of how we could integrate the plugin into the existing pom.
Step 1: Add the following plugin under the build tag:
<plugin>
<groupId>org.spdx</groupId>
<artifactId>spdx-maven-plugin</artifactId>
<version>1.0.2</version>
<executions>
<execution>
<goals>
<goal>createSPDX</goal>
</goals>
</execution>
</executions>
</plugin>
Step 2: Run mvn spdx:createSPD and check the target/site folder. There will be an artifact with the extension .spdx.
CycloneDX also has a Maven plugin that can generate SBOMs in the CDX format. The command for CDX using the below plugin is mvn cdx:makeAggreagateBom. Check the Maven repository for the latest versions.
<plugin>
<groupId>org.cyclonedx</groupId>
<artifactId>cyclonedx-maven-plugin</artifactId>
<version>2.9.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>makeAggregateBom</goal>
</goals>
</execution>
</executions>
</plugin>
There are plugins for programming languages like Python and Go, too.
Trivy is another popular open-source tool that can generate SBOMs for Docker artifacts. Docker images are also formed from a set of dependencies. For example, a Python-based image or a Linux-based image has a ton of libraries that come with them. It is important to inventory them as well because any compliance or vulnerabilities in them will affect your service.
To illustrate how we can scan images with Trivy, let's consider the following example:
Step 1: Pick an image. In this case, let's choose the python:3.13-alpine Docker image.
Step 2: For Windows, download the .exe file from here, and for other platforms, the installation instructions can be found on the Trivy Installation page.
Step 3: Run the following command to output SBOMs in SPDX and CDX formats:
For SPDX:
.\trivy.exe image --format spdx-json --output result.json python:3.13-alpine
For CDX:
.\trivy.exe image --format cyclonedx --output result.json python:3.13-alpine
Kubernetes BOM and Syft are examples of some other open-source tools in the infrastructure space.
Open-source tools typically offer a fragmented view of software risk. For example, Trivy open source only lists open-source vulnerability feeds when using the open-source software version. The vulnerabilities from the commercial vulnerability feed are not provided. Additionally, they don't offer any service-level agreements (SLAs), which might be necessary for companies that provide a strict SLA to their customers.
Support for programming languages is also limited. If we consider the SPDX plugin example that we discussed previously, it supports only a handful of languages (e.g., Java, Python, Go, Haskell, JavaScript).
Attestation is a signed, verifiable declaration that asserts a fact or event. For SBOMs, attestation plays a critical role in establishing trust. Without a mechanism to verify an SBOM's authenticity and origin, its integrity cannot be guaranteed. As a result, by validating the signer through cryptographic attestation, SBOM consumers can ensure that it was generated by an authorized source and remains untampered.
Cosign is a widely adopted open-source tool for signing and attesting supply chain artifacts, including SBOMs. It uses a public and private key system to sign documents and verify their authenticity. By using Cosign, producers can digitally sign an SBOM, and consumers can validate its origin and integrity before trusting or integrating it.
To attest an SBOM with cosign, follow these steps:
Step 1: Generate a public and private key using the command below:
cosign generate-key-pair
Step 2: Sign the SBOM using the private key:
cosign sign-blob --key cosign.key <SBOM artifact>
This command will generate a signature, for example:
MEUCIQD8VwYQUp9ayJqS2V1bOKzTdr7FK5dHDwBHV+nz0qgeVgIgS8wvUuBQnH3ghfq8NSt+ExO+6WY0lY0w92FnVGn3vb4=
Step 3: Embed this signature alongside the SPDX or CDX SBOM file.
Step 4: Consumers can then verify the signed artifact using the public key and signature:
cosign verify-blob --key cosign.pub --signature MEUCIQD8VwYQUp9ayJqS2V1bOKzTdr7FK5dHDwBHV+nz0qgeVgIgS8wvUuBQnH3ghfq8NSt+ExO+6WY0lY0w92FnVGn3vb4= <SBOM artifact>
If the verification is successful, the output will include:
codeblock: cmd
"Verified OK"
A key advantage of using SBOMs is that developers can identify and remediate vulnerabilities early in the development lifecycle, reducing the risk of issues reaching production. More importantly, identifying vulnerabilities must be automated by integrating the vulnerability scanning processes into the builds.
The process of integration is also straightforward and can be adopted with minimal friction.First, as discussed earlier, verify that the SBOM was generated by a trusted and valid source. Next, scan the SBOM for known vulnerabilities. This can be done with Trivy, for example.
To scan a CycloneDX SBOM file:
.\trivy.exe sbom cyclonedx.json
Example output from the command:
| Library | Vulnerability | Severity | Status | Installed Version | Fixed Version | Title | CVE Link |
ch.qos.logback:logback-core |
CVE-2024-12798 |
Medium | Fixed | 1.4.14 | 1.5.1, 1.5.3 |
logback-core: arbitrary code execution via JNDI in EventEvaluator |
CVE-2024-12798 |
net.minidev:json-smart |
CVE-2024-26799 |
High | Fixed | 2.5.1 | 2.5.2 | json-smart: potential DoS via stack exhaustion |
CVE-2024-26799 |
Let's take a look at what each column represents:
To enforce security at build time, configure Trivy to fail the build if any critical or high-severity vulnerabilities occur:
.\trivy.exe sbom --exit-code 0 --severity CRITICAL,HIGH --input cyclonedx.json
The --exit-code flag ensures the build pipeline fails when critical or high-risk vulnerabilities are detected. This strategy helps maintain secure and compliant deployments by preventing insecure artifacts from being released.
While SBOMs have been battle-tested, there are some important factors that need to be considered when incorporating them.
As stated earlier, these are dependencies that your software does not rely on directly, but the vulnerabilities in them can still impact your software. The main challenge is determining how deep to traverse the dependency chain. Because there is no universal standard for how many levels to analyze, the appropriate depth depends on the application's context. For example, if we were to define Level 0 as your application, Level 1 as its direct dependencies, and Level 2 and beyond as transitive dependencies, government or financial systems may require deeper analysis (up to Level 3 or higher), while consumer-facing applications may find Level 1 or 2 sufficient.
Modern applications are built using a mix of open-source, commercial, and internal libraries, and not all of them provide SBOMs. And whether you need an SBOM from a vendor depends on the criticality of their component to your system. For example, SBOMs are essential for the cloud platforms you depend on but may be optional for lightweight utility libraries.
Additionally, different vendors generate SBOMs in different formats and with varying levels of detail. This inconsistency makes it difficult for consumers to normalize and use SBOMs effectively. The problem becomes amplified especially in regulated environments where complete visibility into third-party components is essential.
Unfortunately, there is still a gap in identifying runtime capabilities. For example, it is normal for cloud-native applications to often interact with services such as storage, networking, or computing at runtime, and they are not always represented in the SBOMs. One way you can think of improving the coverage is by defining Infrastructure as Code (IaC), but not all deployments follow IaC, making it difficult to trace such dependencies.
The use of SBOMs has been strongly recommended as part of regulations and standards from countries across the world. Below are examples and their respective statuses as of June 2025.
Executive Order 14028, issued on May 12, 2021 by the United States, lays out a government-wide strategy to improve United States cyber defenses against sophisticated cyberattacks. While it contains multiple directives, one of them is to enhance software supply chain security by providing an SBOM for each and every product.
However, the White House issued a new Executive Order on June 6, 2025, rolling back the requirements for vendors to provide SBOMs. As a result, the obligation to provide the SBOM is no longer federally mandated. Nevertheless, EO 14028 can be considered the foundation for improving supply chain security in the industry.
On December 29, 2022, Section 524B was added to the Federal Food, Drug, and Cosmetic Act. Under this section, any medical device that includes software and is capable of connecting to the internet must provide an SBOM, listing all commercial, open-source, and off-the-shelf software components contained within the device.
The European Union's Cyber Resiliency Act, which came into enforcement in December 2024, addressed the gap with respect to cybersecurity vulnerabilities in software and hardware products (digital elements) as well as inconsistencies in addressing them with timely patches. According to the act, in order to support the identification and management of the vulnerabilities, manufacturers must provide an SBOM, detailing all components within their products.
The threat landscape continues to evolve, and in the age of AI and agentic infrastructure, threat actors will become increasingly sophisticated. The bare minimum we can do to protect ourselves is to reduce the number of vulnerabilities in our software; integrating SBOMs early in the SDLC, well before production, can significantly strengthen an organization's security posture. While it may seem hard in the short run, it will definitely pay dividends in the long run.
Resources for further reading on SBOM standards and tooling:
DZone Article
DZone Article
DZone Article
ADVERTISE
CONTRIBUTE ON DZONE
LEGAL
CONTACT US
Let's be friends: