The software supply chain attacks of recent years — SolarWinds, Codecov, Log4Shell — shifted supply chain security from a theoretical concern to an operational one. SBOMs (Software Bills of Materials) became one of the central responses to this shift. But there’s still significant confusion about what an SBOM actually is, what it can and can’t do, and how to make one useful rather than just compliant.
What is an SBOM?
An SBOM is a formal, machine-readable inventory of the components that make up a piece of software. Think of it as the ingredient list for your application: every library, dependency, framework, and tool that went into building it, along with version numbers and licensing information.
Two formats dominate:
- CycloneDX — developed by OWASP, widely used in security tooling, supports vulnerabilities and license data natively
- SPDX — Linux Foundation standard, stronger focus on license compliance, adopted by many enterprise tools
For most security use cases, CycloneDX is the more capable format.
Why SBOMs Matter
The value of an SBOM is realized in two scenarios:
1. Vulnerability response
When a critical vulnerability is disclosed (another Log4Shell, another OpenSSL), the first question is: do we use this component? Without an SBOM, answering that question requires manually searching codebases, dependency files, and Docker images across every service. With an SBOM, it’s a query.
2. Supply chain integrity
SBOMs, when combined with attestations and signing, let you verify that what you built is what you shipped — and that no component was tampered with between build and deployment.
Generating SBOMs
For application dependencies
Syft by Anchore is the most capable open-source SBOM generator. It scans container images, directories, and archives.
# Generate SBOM for a container image
syft nginx:latest -o cyclonedx-json > sbom.json
# Generate for a local project directory
syft dir:. -o spdx-json > sbom.spdx.json
For container images
# Include OS packages + application dependencies
syft alpine:latest -o cyclonedx-json
# Or with Docker Scout (built into Docker CLI)
docker scout sbom nginx:latest
In CI/CD
# GitHub Actions — generate and attest SBOM on every build
- name: Generate SBOM
uses: anchore/sbom-action@v0
with:
image: ${{ env.IMAGE }}
format: cyclonedx-json
output-file: sbom.cyclonedx.json
- name: Attest SBOM
uses: actions/attest-sbom@v1
with:
subject-name: ${{ env.IMAGE }}
sbom-path: sbom.cyclonedx.json
Scanning SBOMs for Vulnerabilities
Generating an SBOM is step one. Scanning it against known vulnerability databases is where the security value is realized.
Grype pairs naturally with Syft and scans SBOMs against NVD, OSV, GitHub Advisories, and more:
# Scan a container image directly
grype nginx:latest
# Scan a previously generated SBOM
grype sbom:sbom.cyclonedx.json
# Output as table, JSON, or SARIF for CI integration
grype nginx:latest -o sarif > results.sarif
OSV-Scanner from Google scans dependency files and SBOMs against the OSV database:
osv-scanner --sbom sbom.cyclonedx.json
Supply Chain Integrity: Beyond the SBOM
An SBOM tells you what’s in your software. To verify how it was built and that it hasn’t been tampered with, you need:
Sigstore / Cosign
Cosign signs container images and other artifacts using keyless signing via OIDC identity (no long-lived keys to manage):
# Sign an image after pushing
cosign sign --yes ghcr.io/myorg/myapp:v1.0.0
# Verify before deployment
cosign verify ghcr.io/myorg/myapp:v1.0.0 \
--certificate-identity=https://github.com/myorg/myapp/.github/workflows/release.yml@refs/heads/main \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com
SLSA (Supply-chain Levels for Software Artifacts)
SLSA is a framework for supply chain integrity with four levels of assurance. At SLSA Level 3, builds are:
- Run in an isolated, ephemeral environment
- Producing signed provenance attesting to what was built, from what source, by what process
- Verifiable by consumers before deployment
Practical Starting Point
If you’re starting from zero:
- Add Syft to your CI build — generate an SBOM for every container image you publish
- Run Grype on the SBOM — fail the build on critical/high vulnerabilities (with a reasonable policy)
- Publish the SBOM as a build artifact — attached to your release or stored in your registry
- Sign images with Cosign — keyless signing via GitHub Actions OIDC is straightforward
This gives you a solid foundation: you know what’s in your software, you’re scanning it continuously, and you can prove it was built from the source it claims.