Before You Generate: Choose Your Format
The first decision in SBOM generation is format. Two formats dominate:
- SPDX — The Linux Foundation / ISO standard (ISO/IEC 5962:2021). Best for open source license compliance use cases. Available in JSON, YAML, RDF, and tag-value formats.
- CycloneDX — The OWASP standard. Best for security use cases — native support for VEX (Vulnerability Exploitability eXchange), service dependencies, and AI/ML model inventories. Available in JSON and XML.
Both formats are accepted by CISA, FDA, and the EU Cyber Resilience Act. When in doubt, generate both — modern tools make this trivial and the extra overhead is minimal. For regulated industries, confirm with your specific regulator or auditor which format they prefer.
Regardless of format, the NTIA and CISA require each component entry to include: Supplier Name, Component Name, Version, Unique Identifier (PURL or CPE), Dependency Relationships, SBOM Author, and Timestamp. Make sure your tool captures all seven.
Method 1: Syft (Open Source, Recommended for Containers)
Syft, maintained by Anchore, is one of the most capable open source SBOM generators. It supports scanning directory trees, container images, OCI archives, and package manager manifests across dozens of ecosystems. It outputs SPDX and CycloneDX, and is the SBOM generator used internally by many organizations as their first step.
Installation
brew install syft
# Linux / curl install
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
Generate an SBOM from a directory
syft dir:/path/to/your/project -o cyclonedx-json=sbom.cdx.json
# Output SPDX JSON
syft dir:/path/to/your/project -o spdx-json=sbom.spdx.json
# Output both formats simultaneously
syft dir:/path/to/your/project \
-o cyclonedx-json=sbom.cdx.json \
-o spdx-json=sbom.spdx.json
Generate an SBOM from a container image
syft nginx:latest -o cyclonedx-json=nginx-sbom.json
# Scan a local Docker image
syft docker:your-app:latest -o spdx-json=app-sbom.spdx.json
Syft strengths and limitations
Syft is excellent for getting started — it is fast, free, and covers most ecosystems. The key limitation is that it does not perform continuous monitoring. It generates a point-in-time SBOM but does not alert you when new CVEs affect components in that SBOM. For that, you need Grype (Anchore's vulnerability scanner, which consumes Syft SBOMs) or a commercial platform.
Method 2: Trivy (Open Source, Best for Kubernetes/Containers)
Trivy by Aqua Security is the most comprehensive open source security scanner for container and cloud-native environments. It combines vulnerability scanning with SBOM generation and is the tool of choice for teams operating in Kubernetes environments.
brew install trivy
# Generate SBOM from a container image
trivy image --format cyclonedx --output sbom.json nginx:latest
# Generate SBOM from a filesystem
trivy fs --format spdx-json --output sbom.spdx.json /path/to/project
# Scan an SBOM for vulnerabilities
trivy sbom sbom.json
Method 3: CycloneDX CLI (Format-Specific)
The CycloneDX CLI is a tool specifically for working with CycloneDX SBOMs — merging, validating, diffing, and converting between CycloneDX versions. It is not a generator itself but a companion tool for managing CycloneDX artifacts.
The CycloneDX project also provides ecosystem-specific plugins — cyclonedx-npm,
cyclonedx-python, cyclonedx-maven — that generate SBOMs directly
from package manager lock files with high accuracy.
npx @cyclonedx/cyclonedx-npm --output-file sbom.cdx.json
# Generate SBOM from a Python project
pip install cyclonedx-bom
cyclonedx-py -o sbom.json
# Validate an SBOM
cyclonedx validate --input-file sbom.cdx.json --input-format json --input-version v1_5
Method 4: Commercial SCA Platforms (Recommended for Production)
Open source tools generate SBOMs, but they leave you with a static file. In production environments, you need:
- Automatic SBOM generation on every build
- SBOM storage and versioning tied to your release history
- Continuous monitoring — alerts when new CVEs affect components in your SBOM
- License policy enforcement based on SBOM component data
- Compliance reporting for regulators, auditors, or customers
Commercial SCA platforms like Fossity, Black Duck, and Snyk integrate all of these capabilities into a coherent workflow. The SBOM becomes a living artifact — continuously updated and monitored — rather than a point-in-time document.
Integrating SBOM Generation into CI/CD
The most important best practice in SBOM generation is automation. An SBOM that is generated manually once a quarter is not an SBOM — it is a compliance artifact with an expiry date. Best practice is generating a new SBOM on every release build and storing it alongside the build artifact.
GitHub Actions Example
on:
push:
branches: [main]
jobs:
build:
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
- name: Generate SBOM
run: syft dir:. -o spdx-json=sbom.spdx.json -o cyclonedx-json=sbom.cdx.json
- name: Upload SBOM artifacts
uses: actions/upload-artifact@v4
with:
name: sbom
path: sbom.*.json
SBOM Quality: What to Check
Not all SBOMs are equal. A poorly generated SBOM can be worse than no SBOM — it gives a false sense of completeness. Before accepting an SBOM (from your tools or from a vendor), validate:
- Completeness — Does it include transitive dependencies, not just direct ones? Does it cover all build targets (not just the main application)?
- PURL accuracy — Each component should have a Package URL (PURL) that uniquely identifies it and can be matched against vulnerability databases.
- Version specificity — Version ranges (
>=1.0.0) are not enough. Each component should have an exact version. - License data — Is the license field populated? Is it a valid SPDX identifier?
- Timestamp and author — The NTIA minimum elements require these fields.
- Format validity — Use the CycloneDX CLI validator or SPDX tools to verify the SBOM is valid against the spec.
Go Beyond Point-in-Time SBOMs with Fossity
Open source SBOM generators are a great starting point, but they leave you with a static document that goes stale the moment it is generated. Fossity turns SBOM generation into a continuous, automated process — generating accurate SBOMs on every build, storing them with version history, and continuously monitoring them against updated vulnerability intelligence. When a new CVE is disclosed, Fossity immediately cross-references it against every SBOM in your portfolio and alerts you to affected products. This is the difference between SBOM compliance and SBOM security.
Get Started with Fossity →Common Mistakes to Avoid
- Generating the SBOM from the wrong source — Scanning source code manifests can miss components that are only present in the build artifact. For the most accurate SBOM, scan the final container image or build artifact, not just the source tree.
- Not capturing transitive dependencies — Some tools default to direct dependencies only. Always verify that your SBOM includes the full dependency graph.
- Treating the SBOM as a one-time document — An SBOM is only useful if it reflects the current state of the software. Automate generation on every release.
- Storing the SBOM without version control — Your SBOM should be versioned and stored alongside your build artifact, so you can answer questions about any previous release.
- Not validating the output — A syntactically invalid SBOM is useless. Add a validation step to your CI/CD pipeline.