The first SBOM I ever generated by hand — manually listing out every dependency and version for a mid-sized Node.js project — took me the better part of an afternoon, and it was outdated within a week when a routine npm update changed half the versions. That experience is exactly why I never generate an SBOM manually anymore. It has to be automated, or it’s not worth doing at all.
If you already understand what an SBOM is (if not, check out SBOM Explained for Beginners first), this post is the practical follow-up: how to actually wire automatic SBOM generation into your build process.
Where SBOM Generation Fits in Your Pipeline
The right place to generate an SBOM is as part of your CI/CD build process — not as a separate manual task someone remembers to do before a release.
flowchart LR
A[Code Commit] --> B[CI Pipeline Triggered]
B --> C[Dependency Resolution]
C --> D[SBOM Generation Tool]
D --> E[SBOM Artifact - SPDX/CycloneDX]
E --> F[Vulnerability Scanner]
E --> G[Stored with Release Artifacts]
F --> H[Alert on Known CVEs]
Generating the SBOM at build time guarantees it reflects the exact dependency versions actually shipped — not an approximation created after the fact.
Choosing an SBOM Generation Tool
There are several solid open-source tools depending on your ecosystem:
| Tool | Best For | Output Formats |
|---|---|---|
| Syft | Container images, filesystems, multiple languages | SPDX, CycloneDX |
| CycloneDX CLI/plugins | Language-specific (npm, Maven, Python, etc.) | CycloneDX |
| SPDX SBOM Generator | Multi-language projects | SPDX |
| Trivy | Combines SBOM generation with vulnerability scanning | SPDX, CycloneDX |
I personally reach for Syft most often because it works across container images, directories, and archives without needing a different tool per language.
Step-by-Step: Generating an SBOM With Syft
1. Install Syft
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
2. Generate an SBOM for a directory
syft dir:. -o cyclonedx-json=sbom.json
3. Generate an SBOM for a container image
syft myapp:latest -o spdx-json=sbom-image.json
That’s it — Syft scans the filesystem or image layers, identifies every package it can detect, and outputs a structured SBOM file in seconds.
Automating SBOM Generation in CI/CD
Here’s how I typically wire this into a GitHub Actions workflow:
name: Generate SBOM
on:
push:
branches: [main]
jobs:
sbom:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Syft
run: curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
- name: Generate SBOM
run: syft dir:. -o cyclonedx-json=sbom.json
- name: Upload SBOM Artifact
uses: actions/upload-artifact@v4
with:
name: sbom
path: sbom.json
This runs on every push to main, so an up-to-date SBOM is always attached to the build — no one has to remember to generate it manually.
Generating SBOMs for Container Images
Since so much of what I deploy runs in containers, I generate the SBOM directly from the built image rather than just the source directory, since base images and OS-level packages introduce additional dependencies that source-only scans miss.
docker build -t myapp:latest .
syft myapp:latest -o cyclonedx-json=image-sbom.json
If you’re newer to container workflows, it’s worth reviewing Docker fundamentals since image layer composition directly affects what shows up in your SBOM.
Connecting SBOM Generation to Vulnerability Scanning
An SBOM by itself is just an inventory — the real value comes from feeding it into a scanner that checks each component against known vulnerability databases.
# Using Grype alongside Syft
grype sbom:./sbom.json
I chain these together in CI so that every build automatically produces both an inventory and a vulnerability report, which I cover in more depth in Dependency Scanning Explained and Top Software Composition Analysis (SCA) Tools.
Where to Store Generated SBOMs
Once generated, I don’t just let SBOMs sit as ephemeral CI artifacts — I attach them to the release itself so they’re available for audits, customer requests, or incident response long after the build has passed:
- Attach as a release asset in GitHub Releases
- Push to an internal artifact repository alongside the build
- Store in a dedicated SBOM management platform if operating at scale
Common Mistakes When Automating SBOM Generation
- Generating SBOMs only from source code, missing OS-level packages baked into container images
- Treating SBOM generation as a manual, pre-release checklist item instead of an automated pipeline step
- Not storing SBOMs long-term, losing historical inventory for older releases
- Generating an SBOM but never feeding it into a vulnerability scanner
- Using inconsistent formats across projects, making aggregation difficult
Best Practices Checklist
| Practice | Benefit |
|---|---|
| Generate in CI/CD, not manually | Always current, zero human effort |
| Scan both source and container images | Captures OS-level and application dependencies |
| Pick one standard format org-wide | Simplifies tooling and aggregation |
| Pair with a vulnerability scanner | Turns inventory into actionable insight |
| Archive SBOMs with each release | Supports audits and incident response |
FAQs
Which is easier to automate, SPDX or CycloneDX? Both are well supported by modern tooling. CycloneDX tends to have slightly better tooling for direct vulnerability scanning integration, which is why I lean toward it for security-focused pipelines.
Do I need to generate a new SBOM for every build, or just releases? I generate on every build to main, but at minimum, every tagged release should have its own SBOM, since dependency versions can change between releases.
Can I generate an SBOM for a project with no build system, like a static site? Yes, tools like Syft can still scan the filesystem for package manifests (like package-lock.json) even without a traditional build step.
Does SBOM generation slow down my CI pipeline significantly? Generally no — most SBOM tools run in seconds to a few minutes depending on project size, which is a small cost for the visibility gained.
Conclusion
Manual SBOM generation doesn’t scale and goes stale almost immediately. The only sustainable approach is automating it directly into your CI/CD pipeline, scanning both source dependencies and container images, and feeding the result into a vulnerability scanner. Once that pipeline is wired up, you get continuous, always-current visibility into exactly what’s inside your software — without anyone having to think about it.
