How-To Guide

How to Create Your First SBOM

A practical, step-by-step guide to generating your first Software Bill of Materials using open-source tools and integrating it into your development workflow.

Yukti Singhal
Security Engineer
5 min read

If you ship software, you need a Software Bill of Materials. That is not a marketing pitch. It is the reality of modern software development, where regulatory pressure from frameworks like Executive Order 14028 and customer procurement requirements are making SBOMs table stakes for doing business.

But here is the good news: creating your first SBOM is not as complicated as it sounds. In this guide, I will walk you through generating one from scratch, choosing the right format, and making it useful rather than just another compliance artifact collecting dust.

What Exactly Is an SBOM?

An SBOM is a structured inventory of every component in your software. Think of it like a nutrition label for code. It lists your direct dependencies, transitive dependencies, their versions, licenses, and suppliers.

There are two dominant formats:

  • CycloneDX - Designed for security use cases. Lightweight, supports vulnerability references natively, and has strong tooling in the application security space.
  • SPDX - Born from the Linux Foundation. More license-focused historically, but has evolved to handle security metadata. It became an ISO standard (ISO/IEC 5962:2021).

For most teams starting out, I recommend CycloneDX. The tooling is more straightforward, the format is less verbose, and security teams tend to find it easier to consume.

Prerequisites

Before we start, make sure you have:

  • A project with a package manager (npm, Maven, pip, Go modules, etc.)
  • Node.js installed (for the CycloneDX CLI tools)
  • About 15 minutes

Step 1: Install a Generation Tool

The CycloneDX project maintains generators for most ecosystems. Pick the one matching your stack:

For Node.js/npm projects:

npm install -g @cyclonedx/cyclonedx-npm

For Python projects:

pip install cyclonedx-bom

For Java/Maven projects: Add the CycloneDX Maven plugin to your pom.xml:

<plugin>
  <groupId>org.cyclonedx</groupId>
  <artifactId>cyclonedx-maven-plugin</artifactId>
  <version>2.7.9</version>
</plugin>

For Go projects:

go install github.com/CycloneDX/cyclonedx-gomod/cmd/cyclonedx-gomod@latest

If you want a single tool that works across multiple ecosystems, Syft from Anchore is excellent:

curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin

Step 2: Generate the SBOM

Point your tool at the project root. Here is what that looks like for a Node.js project:

cyclonedx-npm --output-file sbom.json

For Syft, it is even simpler because it auto-detects the ecosystem:

syft dir:. -o cyclonedx-json=sbom.json

If you are working with container images, Syft can scan those directly:

syft myregistry.io/myapp:latest -o cyclonedx-json=sbom.json

Step 3: Validate the Output

Do not just generate the file and call it done. Open it up and sanity-check it.

A valid CycloneDX SBOM should contain:

  • bomFormat - Should be "CycloneDX"
  • specVersion - Ideally 1.4 or later
  • components - Array of all detected components
  • Each component should have a purl (Package URL) for unambiguous identification

You can validate the structure using the CycloneDX CLI:

npx @cyclonedx/cyclonedx-cli validate --input-file sbom.json --input-format json

Check the component count against what you expect. If your project has 200 dependencies in the lock file but the SBOM lists 50, something went wrong. Usually it means the tool only captured direct dependencies and missed transitive ones.

Step 4: Enrich with Vulnerability Data

A raw SBOM tells you what you have. The real value comes from cross-referencing that inventory against known vulnerabilities.

You can do this manually using tools like grype:

grype sbom:sbom.json

This will match every component in your SBOM against vulnerability databases like the NVD, GitHub Security Advisories, and OSV, then output a list of known CVEs affecting your dependencies.

Step 5: Automate Generation in CI/CD

A one-time SBOM is a snapshot. What you actually need is an SBOM generated on every build so it stays current. Add it to your CI pipeline:

# GitHub Actions example
- name: Generate SBOM
  run: |
    syft dir:. -o cyclonedx-json=sbom.json
    
- name: Upload SBOM artifact
  uses: actions/upload-artifact@v3
  with:
    name: sbom
    path: sbom.json

For container-based deployments, generate the SBOM from the final image, not just the source code. The image may include OS-level packages that source-level tools will miss.

Common Pitfalls

Lock files matter. If your lock file is out of date or missing, the SBOM will be incomplete. Always run your package manager's install or lock command before generating.

Build-time dependencies are not runtime dependencies. Some tools include devDependencies by default. Decide whether you want a comprehensive SBOM or a runtime-only SBOM and configure accordingly.

Transitive dependency depth. Some generators have depth limits. Make sure yours captures the full dependency tree. A vulnerability three levels deep is still your vulnerability.

Reproducibility. Generate the SBOM from lock files, not floating version ranges. You want the SBOM to describe exactly what was built, not what could have been built.

What to Do with Your SBOM

Once you have it, an SBOM enables several workflows:

  1. Vulnerability monitoring - Continuously scan your SBOM against updated vulnerability databases.
  2. License compliance - Audit all included licenses against your organization's approved list.
  3. Incident response - When the next Log4Shell drops, search your SBOMs to know in minutes whether you are affected.
  4. Customer and regulatory requirements - Share SBOMs with customers who require them as part of procurement.

How Safeguard.sh Helps

Safeguard.sh automates the entire SBOM lifecycle. It generates SBOMs across your projects, continuously monitors them for new vulnerabilities, and provides a centralized dashboard where your security team can track component risk across your entire portfolio. Instead of stitching together five open-source tools and writing custom glue code, you get a single platform that handles generation, storage, vulnerability correlation, and policy enforcement out of the box. If you are just getting started with SBOMs, Safeguard.sh removes the tooling complexity so you can focus on actually improving your security posture.

Never miss an update

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