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:
- Vulnerability monitoring - Continuously scan your SBOM against updated vulnerability databases.
- License compliance - Audit all included licenses against your organization's approved list.
- Incident response - When the next Log4Shell drops, search your SBOMs to know in minutes whether you are affected.
- 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.