Generate, augment, enrich, and manage SBOMs in your CI/CD pipeline. Works standalone or with sbomify.
Recommended: Use the GitHub Action or Docker image—they include all SBOM generators (Trivy, Syft, cdxgen) pre-installed. For other CI platforms, see examples below. A pip package is also available for advanced use cases.
Why generate SBOMs in CI/CD? Generating SBOMs at build time enables cryptographic signing and attestation, creating a verifiable chain of trust from source to artifact. Learn more about the SBOM lifecycle.
- uses: sbomify/github-action@master
env:
LOCK_FILE: requirements.txt
OUTPUT_FILE: sbom.cdx.json
UPLOAD: false
ENRICH: trueThat's it! This generates a CycloneDX SBOM from your lockfile and enriches it with metadata from package registries. For SPDX format, set SBOM_FORMAT: spdx.
- Generate SBOMs from lockfiles (Python, Node, Rust, Go, Ruby, Dart, C++) in CycloneDX or SPDX format
- Generate SBOMs from Docker images
- Inject additional packages not in lockfiles (vendored code, runtime deps, system libraries)
- Augment with business metadata (supplier, authors, licenses, lifecycle phase) from config file or sbomify
- VCS Auto-Detection — Automatically adds repository URL, commit SHA, and branch info from CI environment
- Enrich with package metadata from PyPI, pub.dev, crates.io, Conan Center, deps.dev, and more
- Audit Trail — Every SBOM modification logged with timestamps for attestation and compliance
- Upload to sbomify for collaboration and vulnerability management
- Tag SBOMs with product releases
- Attest with GitHub's build provenance
- uses: sbomify/github-action@master
env:
LOCK_FILE: poetry.lock
OUTPUT_FILE: sbom.cdx.json
UPLOAD: false
COMPONENT_NAME: my-app
COMPONENT_VERSION: ${{ github.ref_name }}
ENRICH: trueAdd business metadata without a sbomify account using a local config file:
- uses: sbomify/github-action@master
env:
LOCK_FILE: requirements.txt
OUTPUT_FILE: sbom.cdx.json
UPLOAD: false
AUGMENT: true # Uses sbomify.json in project root
ENRICH: trueSee Augmentation Config File for the config format.
- uses: sbomify/github-action@master
env:
TOKEN: ${{ secrets.SBOMIFY_TOKEN }}
COMPONENT_ID: your-component-id
LOCK_FILE: requirements.txt
AUGMENT: true
ENRICH: true- uses: sbomify/github-action@master
env:
TOKEN: ${{ secrets.SBOMIFY_TOKEN }}
COMPONENT_ID: your-component-id
API_BASE_URL: https://sbomify.yourcompany.com
LOCK_FILE: requirements.txt
AUGMENT: true
ENRICH: true- uses: sbomify/github-action@master
env:
DOCKER_IMAGE: my-app:latest
OUTPUT_FILE: sbom.cdx.json
UPLOAD: false
ENRICH: trueGenerate SPDX instead of CycloneDX:
- uses: sbomify/github-action@master
env:
LOCK_FILE: requirements.txt
OUTPUT_FILE: sbom.spdx.json
SBOM_FORMAT: spdx
UPLOAD: false
ENRICH: true- uses: sbomify/github-action@master
env:
LOCK_FILE: Cargo.lock
OUTPUT_FILE: sbom.cdx.json
UPLOAD: false
ENRICH: true
- uses: actions/attest-build-provenance@v1
with:
subject-path: sbom.cdx.jsonEvery modification made to your SBOM is tracked and recorded for attestation and compliance purposes. The audit trail captures:
- Overrides: Component name, version, and PURL changes from CLI/environment
- Augmentation: Supplier, manufacturer, authors, licenses, VCS info, lifecycle phase
- Enrichment: Per-component metadata additions (description, license, publisher, URLs)
- Sanitization: PURL normalizations, URL validations, stub components added
- Summary table (always visible) — Shows counts by category
audit_trail.txtfile — Detailed log written alongside your SBOM output- Attestation output — Full audit trail printed in collapsible GitHub Actions group
Summary:
┌─────────────────────┬───────┐
│ Metric │ Value │
├─────────────────────┼───────┤
│ Overrides applied │ 3 │
│ Components enriched │ 42 │
│ Sanitization fixes │ 5 │
└─────────────────────┴───────┘
audit_trail.txt:
# SBOM Audit Trail
# Generated: 2026-01-18T12:34:56Z
# Input: requirements.txt
# Output: sbom.cdx.json
## Override
[2026-01-18T12:34:56Z] OVERRIDE component.version SET "2.0.0" (source: cli/env)
[2026-01-18T12:34:56Z] OVERRIDE component.name MODIFIED "old-name" -> "my-app" (source: cli/env)
## Enrichment
[2026-01-18T12:34:57Z] ENRICHMENT pkg:pypi/requests@2.31.0 license ADDED (source: pypi)
[2026-01-18T12:34:57Z] ENRICHMENT pkg:pypi/requests@2.31.0 description ADDED (source: pypi)
All timestamps are in UTC (ISO 8601 format with Z suffix).
| Variable | Required | Description |
|---|---|---|
LOCK_FILE |
† | Path to lockfile (requirements.txt, poetry.lock, Cargo.lock, etc.) |
SBOM_FILE |
† | Path to existing SBOM file |
DOCKER_IMAGE |
† | Docker image name |
OUTPUT_FILE |
No | Write final SBOM to this path |
SBOM_FORMAT |
No | Output format: cyclonedx (default) or spdx |
ENRICH |
No | Add metadata from package registries |
TOKEN |
‡ | sbomify API token |
COMPONENT_ID |
‡ | sbomify component ID |
AUGMENT |
No | Add metadata from sbomify |
COMPONENT_NAME |
No | Override component name in SBOM |
COMPONENT_VERSION |
No | Override component version in SBOM |
COMPONENT_PURL |
No | Add or override component PURL in SBOM |
PRODUCT_RELEASE |
No | Tag SBOM with product releases (see Product Releases) |
UPLOAD |
No | Upload SBOM (default: true) |
UPLOAD_DESTINATIONS |
No | Comma-separated destinations: sbomify, dependency-track (default: sbomify) |
API_BASE_URL |
No | Override sbomify API URL for self-hosted instances |
ADDITIONAL_PACKAGES_FILE |
No | Custom path to additional packages file |
ADDITIONAL_PACKAGES |
No | Inline PURLs to inject (comma or newline separated) |
DISABLE_VCS_AUGMENTATION |
No | Set to true to disable auto-detection of VCS info from CI environment |
† One of LOCK_FILE, SBOM_FILE, or DOCKER_IMAGE is required (pick one)
‡ Required when uploading to sbomify or using sbomify features (AUGMENT, PRODUCT_RELEASE)
When uploading to Dependency Track (UPLOAD_DESTINATIONS=dependency-track), configure with DTRACK_* prefixed environment variables:
| Variable | Required | Description |
|---|---|---|
DTRACK_API_KEY |
Yes | Dependency Track API key |
DTRACK_API_URL |
Yes | Full API base URL (e.g., https://dtrack.example.com/api) |
DTRACK_PROJECT_ID |
§ | Project UUID (alternative to using COMPONENT_NAME/COMPONENT_VERSION) |
DTRACK_AUTO_CREATE |
No | Auto-create project if it doesn't exist (default: false) |
§ Either DTRACK_PROJECT_ID or both COMPONENT_NAME and COMPONENT_VERSION are required
Note: Dependency Track only supports CycloneDX format (not SPDX). It uses the global
COMPONENT_NAMEandCOMPONENT_VERSIONfor project identification.
- uses: sbomify/github-action@master
env:
LOCK_FILE: requirements.txt
OUTPUT_FILE: sbom.cdx.json
UPLOAD: true
UPLOAD_DESTINATIONS: dependency-track
COMPONENT_NAME: my-app
COMPONENT_VERSION: ${{ github.ref_name }}
DTRACK_API_KEY: ${{ secrets.DTRACK_API_KEY }}
DTRACK_API_URL: https://dtrack.example.com/api
DTRACK_AUTO_CREATE: true
ENRICH: true- uses: sbomify/github-action@master
env:
LOCK_FILE: requirements.txt
OUTPUT_FILE: sbom.cdx.json
UPLOAD: true
UPLOAD_DESTINATIONS: sbomify,dependency-track
# Component metadata (used by both sbomify and Dependency Track)
COMPONENT_NAME: my-app
COMPONENT_VERSION: ${{ github.ref_name }}
# sbomify config
TOKEN: ${{ secrets.SBOMIFY_TOKEN }}
COMPONENT_ID: your-component-id
# Dependency Track config
DTRACK_API_KEY: ${{ secrets.DTRACK_API_KEY }}
DTRACK_API_URL: https://dtrack.example.com/api
DTRACK_AUTO_CREATE: true
ENRICH: trueTag your SBOMs with product releases for version tracking and release management in sbomify.
- uses: sbomify/github-action@master
env:
TOKEN: ${{ secrets.SBOMIFY_TOKEN }}
COMPONENT_ID: your-component-id
LOCK_FILE: requirements.txt
PRODUCT_RELEASE: '["product_id:v1.0.0"]'Format: JSON array of "product_id:version" strings. You can tag multiple releases:
PRODUCT_RELEASE: '["product_id_1:v1.0.0", "product_id_2:v2.0.0"]'Behavior:
- Get-or-create: If the release already exists, it's reused. If not, it's created automatically.
- Tagging: The uploaded SBOM is associated with each specified release.
- Partial failures: If some releases succeed and others fail, the action logs a warning but continues.
Note: Requires
TOKENandCOMPONENT_IDto be set, as this feature interacts with the sbomify API.
| Language | Files |
|---|---|
| Python | requirements.txt, poetry.lock, Pipfile.lock, uv.lock, pyproject.toml |
| JavaScript | package.json, package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lock |
| Java | pom.xml, build.gradle, build.gradle.kts, gradle.lockfile |
| Go | go.mod, go.sum |
| Rust | Cargo.lock |
| Ruby | Gemfile.lock |
| PHP | composer.json, composer.lock |
| .NET/C# | packages.lock.json |
| Swift | Package.swift, Package.resolved |
| Dart | pubspec.lock |
| Elixir | mix.lock |
| Scala | build.sbt |
| C++ | conan.lock |
| Terraform | .terraform.lock.hcl |
Inject packages not captured by lockfile scanning—vendored code, runtime dependencies, or system libraries.
If additional_packages.txt exists in your working directory, it's automatically detected:
# additional_packages.txt
# Runtime dependencies not in lockfile
pkg:pypi/requests@2.31.0
pkg:npm/lodash@4.17.21
# System libraries
pkg:deb/debian/openssl@3.0.11File format:
- One PURL per line
- Lines starting with
#are comments - Empty lines are ignored
- uses: sbomify/github-action@master
env:
LOCK_FILE: requirements.txt
ADDITIONAL_PACKAGES_FILE: .sbomify/extra-packages.txtFor dynamic or programmatic use:
- uses: sbomify/github-action@master
env:
LOCK_FILE: requirements.txt
ADDITIONAL_PACKAGES: "pkg:pypi/requests@2.31.0,pkg:npm/lodash@4.17.21"Append packages across multiple steps:
- name: Add Python runtime deps
run: echo "pkg:pypi/requests@2.31.0" >> additional_packages.txt
- name: Add system libraries
run: |
echo "pkg:deb/debian/openssl@3.0.11" >> additional_packages.txt
echo "pkg:deb/debian/libssl3@3.0.11" >> additional_packages.txt
- name: Generate SBOM
uses: sbomify/github-action@master
env:
LOCK_FILE: requirements.txt
# No additional config needed - file is auto-detectedMerge behavior: If both file and inline packages are provided, they are merged and deduplicated. Injected packages flow through augmentation and enrichment like any other component.
generate-sbom:
image: sbomifyhub/sbomify-action
variables:
LOCK_FILE: poetry.lock
OUTPUT_FILE: sbom.cdx.json
UPLOAD: "false"
ENRICH: "true"
script:
- /sbomify.shpipelines:
default:
- step:
script:
- pipe: docker://sbomifyhub/sbomify-action:latest
variables:
LOCK_FILE: poetry.lock
OUTPUT_FILE: sbom.cdx.json
UPLOAD: "false"
ENRICH: "true"docker run --rm -v $(pwd):/code \
-e LOCK_FILE=/code/requirements.txt \
-e OUTPUT_FILE=/code/sbom.cdx.json \
-e UPLOAD=false \
sbomifyhub/sbomify-actionFor local development or environments where Docker isn't available, install via pip:
pip install sbomify-actionRun without arguments to see available options:
sbomify-actionOr use CLI arguments directly:
sbomify-action --lock-file requirements.txt --enrich --no-upload -o sbom.cdx.jsonEnvironment variables also work (useful for scripts):
export LOCK_FILE=requirements.txt
export OUTPUT_FILE=sbom.cdx.json
export UPLOAD=false
export ENRICH=true
sbomify-actionNote: SBOM generation requires external tools (trivy, syft, or cdxgen) to be installed separately. The Docker image includes all tools pre-installed, which is why it's the recommended approach.
Augmentation (AUGMENT=true) adds organizational metadata to your SBOM—supplier info, authors, licenses, and lifecycle phase. This addresses NTIA Minimum Elements and CISA 2025 requirements.
Augmentation sources (in priority order):
- Local config file (
sbomify.json) — No account needed. Local values take precedence. - sbomify API — Fetches metadata configured in your sbomify component. Requires account.
Enrichment (ENRICH=true) fetches package metadata from public registries. No account needed.
Create sbomify.json in your project root to provide augmentation metadata:
{
"lifecycle_phase": "build",
"supplier": {
"name": "My Company",
"url": ["https://example.com"],
"contacts": [{"name": "Support", "email": "support@example.com"}]
},
"authors": [
{"name": "John Doe", "email": "john@example.com"}
],
"licenses": ["MIT"],
"security_contact": "https://example.com/.well-known/security.txt",
"release_date": "2024-06-15",
"support_period_end": "2026-12-31",
"end_of_life": "2028-12-31"
}Supported fields:
| Field | Description | SBOM Mapping |
|---|---|---|
lifecycle_phase |
Generation context (CISA 2025) | CycloneDX 1.5+: metadata.lifecycles[].phase; SPDX: creationInfo.creatorComment |
supplier |
Organization that supplies the component | CycloneDX: metadata.supplier; SPDX: packages[].supplier |
authors |
List of component authors | CycloneDX: metadata.authors[]; SPDX: creationInfo.creators[] |
licenses |
SPDX license identifiers | CycloneDX: metadata.licenses[]; SPDX: Document-level licenses |
security_contact |
URL/email for vulnerability reporting (CRA) | CycloneDX 1.5+: externalReferences[type=security-contact]; SPDX: externalRefs[category=SECURITY] |
release_date |
ISO-8601 date when component was released | CycloneDX 1.5+: metadata.lifecycles[] + property; SPDX: external ref |
support_period_end |
ISO-8601 date when security support ends | CycloneDX 1.5+: metadata.lifecycles[] + property; SPDX: validUntilDate + external ref |
end_of_life |
ISO-8601 date when all support ends | CycloneDX 1.5+: metadata.lifecycles[] + property; SPDX: external ref |
vcs_url |
Repository URL (overrides CI auto-detection) | CycloneDX: externalReferences[type=vcs]; SPDX: downloadLocation |
vcs_commit_sha |
Full commit SHA | Appended to VCS URL as @sha |
vcs_ref |
Branch or tag name | Added as comment/context |
Valid lifecycle_phase values: design, pre-build, build, post-build, operations, discovery, decommission
Valid security_contact formats:
https://example.com/.well-known/security.txt— security.txt URL (recommended)mailto:security@example.com— email addresshttps://example.com/security/report— disclosure procedure URL
Valid date formats for release_date, support_period_end, end_of_life: ISO-8601 date string (e.g., 2028-12-31)
Lifecycle date fields explained:
release_date— When the component was publicly releasedsupport_period_end— When security-only support ends (bugfixes stop, only security patches after this)end_of_life— When all support ends (no more updates of any kind)
Priority: Local config values override sbomify API values when both are available.
When running in CI environments, sbomify automatically detects and adds VCS (Version Control System) information to your SBOM:
| CI Platform | Auto-Detected Fields |
|---|---|
| GitHub Actions | Repository URL, commit SHA, branch/tag (supports GitHub Enterprise Server) |
| GitLab CI | Project URL, commit SHA, ref name (supports self-managed instances) |
| Bitbucket Pipelines | Repository URL, commit SHA, branch/tag |
What's added to the SBOM:
- CycloneDX: VCS external reference on root component with
git+https://...@shaformat - SPDX:
downloadLocationwith commit-pinned URL,sourceInfowith build context, VCS external reference
Overriding auto-detected values:
Add VCS fields to sbomify.json to override auto-detected values (useful for self-hosted instances):
{
"vcs_url": "https://github.mycompany.com/org/repo",
"vcs_commit_sha": "abc123def456",
"vcs_ref": "main"
}Disabling VCS augmentation:
Set the environment variable to disable VCS information entirely:
env:
DISABLE_VCS_AUGMENTATION: "true"| Source | Package Types | Data |
|---|---|---|
| License DB | Alpine, Wolfi, Ubuntu, Rocky, Alma, CentOS, Fedora, Amazon Linux | License, description, supplier, homepage |
| Lifecycle | Python, PHP, Go, Rust, Django, Rails, Laravel, React, Vue | CLE (release date, end-of-support, end-of-life) |
| PyPI | Python | License, author, homepage |
| pub.dev | Dart | License, author, homepage, repo |
| crates.io | Rust/Cargo | License, author, homepage, repo, description |
| Conan Center | C/C++ (Conan) | License, author, homepage, repo, description |
| Debian Sources | Debian packages | Maintainer, description, homepage |
| deps.dev | Python, npm, Maven, Go, Ruby, NuGet (+ Rust fallback) | License, homepage, repo |
| ecosyste.ms | All major ecosystems | License, description, maintainer |
| ClearlyDefined | Python, npm, Cargo, Maven, Ruby, NuGet, Go | License, attribution |
| Repology | Linux distros | License, homepage |
For Linux distro packages, sbomify uses pre-computed databases that provide comprehensive package metadata. The databases are built by pulling data directly from official distro sources (Alpine APKINDEX, Ubuntu/Debian apt repositories, RPM repos) and normalizing it into a consistent format with validated SPDX license expressions.
- Generated automatically on each release from official distro repositories
- Downloaded on-demand from GitHub Releases during enrichment (checks up to 5 recent releases)
- Cached locally (~/.cache/sbomify/license-db/) for faster subsequent runs
- Normalized — vendor-specific license strings converted to valid SPDX expressions
Data provided:
| Field | Description |
|---|---|
| License | SPDX-validated license expression |
| Description | Package summary |
| Supplier | Package maintainer/vendor |
| Homepage | Project website URL |
| Download URL | Package download location |
| Maintainer | Name and email |
Note: CLE (lifecycle) data is now provided by the dedicated Lifecycle enrichment source. See Lifecycle Enrichment below.
Supported distros:
| Distro | Versions |
|---|---|
| Alpine | 3.13–3.21 |
| Wolfi | rolling |
| Debian | 11, 12, 13 |
| Ubuntu | 20.04, 22.04, 24.04 |
| Rocky Linux | 8, 9 |
| AlmaLinux | 8, 9 |
| CentOS | Stream 8, Stream 9 |
| Fedora | 39, 40, 41, 42 |
| Amazon Linux | 2, 2023 |
The license database is the primary source for Linux distro packages, taking precedence over other enrichment sources. If a package isn't found in the database, sbomify falls back to Repology and ecosyste.ms.
Local generation (advanced): If you need a database for an unsupported version or want to generate offline:
sbomify-license-db --distro alpine --version 3.20 --output alpine-3.20.json.gzNote: Local generation fallback is disabled by default (Ubuntu/Debian can take hours to generate). Set
SBOMIFY_ENABLE_LICENSE_DB_GENERATION=trueto enable it.
sbomify provides CLE (Common Lifecycle Enumeration) data including release dates, end-of-support, and end-of-life dates. This enables automated tracking of outdated or unsupported components.
Supported operating systems:
| OS | Tracked Versions |
|---|---|
| Debian | 10, 11, 12 |
| Ubuntu | 20.04, 22.04, 24.04 |
| Alpine | 3.13–3.21 |
| Rocky Linux | 8, 9 |
| AlmaLinux | 8, 9 |
| CentOS | Stream 8, Stream 9 |
| Fedora | 39–42 |
| Amazon Linux | 2, 2023 |
Operating system components (CycloneDX type: operating-system) are enriched with lifecycle data based on their name and version.
Supported runtimes and frameworks:
| Package | Tracked Versions | PURL Matching |
|---|---|---|
| Python | 2.7, 3.10–3.14 | All types (pypi, deb, rpm, apk) |
| PHP | 7.4, 8.0–8.5 | All types (composer, deb, rpm, apk) |
| Go | 1.22–1.25 | All types (golang, deb, rpm, apk) |
| Rust | 1.90–1.92 | All types (cargo, deb, rpm, apk) |
| Django | 4.2, 5.2, 6.0 | PyPI only |
| Rails | 7.0–8.1 (+ all component gems) | RubyGems only |
| Laravel | 10–13 | Composer only |
| React | 17–19 | npm only |
| Vue | 2, 3 | npm only |
How it works:
- OS components: Detected by CycloneDX
type: operating-system, matched by name/version - Runtimes/frameworks: Matched by name pattern across all package managers
- Version cycle extracted from full version (e.g.,
3.12.7→3.12,12.12→12) - Lifecycle properties added:
cdx:lifecycle:milestone:generalAvailability,cdx:lifecycle:milestone:endOfSupport,cdx:lifecycle:milestone:endOfLife
Note: Arbitrary OS packages (curl, nginx, openssl, etc.) do not receive lifecycle data. Only the operating system itself and explicitly tracked runtimes/frameworks get CLE data.
Example enriched OS component:
{
"type": "operating-system",
"name": "debian",
"version": "12.12",
"properties": [
{"name": "cdx:lifecycle:milestone:generalAvailability", "value": "2023-06-10"},
{"name": "cdx:lifecycle:milestone:endOfSupport", "value": "2026-06-10"},
{"name": "cdx:lifecycle:milestone:endOfLife", "value": "2028-06-30"}
]
}This allows downstream tools to identify components running on unsupported operating systems or runtimes.
SBOM generators like Trivy and Syft focus on dependency detection—they produce name, version, and PURL, but typically leave metadata fields empty. sbomify queries package registries to fill in these gaps, improving license compliance and supply chain visibility.
Scanners detect packages but don't fetch metadata. Here's what a typical Trivy component looks like:
{
"type": "library",
"name": "django",
"version": "5.1",
"purl": "pkg:pypi/django@5.1"
}After sbomify enrichment, the same component includes supplier, license, and reference URLs:
{
"type": "library",
"name": "django",
"version": "5.1",
"purl": "pkg:pypi/django@5.1",
"publisher": "Django Software Foundation",
"description": "A high-level Python web framework...",
"licenses": [{"expression": "BSD-3-Clause"}],
"externalReferences": [
{"type": "website", "url": "https://www.djangoproject.com/"},
{"type": "vcs", "url": "https://github.com/django/django"},
{"type": "distribution", "url": "https://pypi.org/project/Django/"}
]
}sbomify attempts to populate these fields for each component:
| Field | Description | Coverage |
|---|---|---|
| Supplier/Publisher | Package maintainer or organization | High for popular registries |
| License | SPDX license expression | High (most registries require it) |
| Description | Package summary | High |
| Homepage | Project website | Medium-High |
| Repository | Source code URL | Medium-High |
| Download URL | Registry/distribution link | High |
| Issue Tracker | Bug reporting URL | Medium |
Coverage varies by ecosystem. Popular packages on PyPI, npm, and crates.io have excellent metadata. Linux distros (Alpine, Ubuntu, Rocky, Alma, CentOS, Fedora, Amazon Linux, Wolfi) have high license coverage through pre-computed license databases. sbomify queries multiple sources with fallbacks, but some fields may remain empty for obscure packages.
sbomify queries sources in priority order, stopping when data is found:
| Ecosystem | Primary Source | Fallback Sources |
|---|---|---|
| Python | PyPI API | deps.dev → ecosyste.ms → ClearlyDefined |
| JavaScript | deps.dev | ecosyste.ms → ClearlyDefined |
| Rust | crates.io API | deps.dev → ecosyste.ms → ClearlyDefined |
| Go | deps.dev | ecosyste.ms → ClearlyDefined |
| Ruby | deps.dev | ecosyste.ms → ClearlyDefined |
| Java/Maven | deps.dev | ecosyste.ms → ClearlyDefined |
| NuGet | deps.dev | ecosyste.ms → ClearlyDefined |
| Dart | pub.dev API | ecosyste.ms |
| C++ (Conan) | Conan Center API | ecosyste.ms |
| Debian | Debian Sources | Repology → ecosyste.ms |
| Ubuntu | License DB | Repology → ecosyste.ms |
| Alpine | License DB | Repology → ecosyste.ms |
| Wolfi | License DB | Repology → ecosyste.ms |
| Rocky/Alma/CentOS | License DB | Repology → ecosyste.ms |
| Fedora | License DB | Repology → ecosyste.ms |
| Amazon Linux | License DB | Repology → ecosyste.ms |
- Network required: Enrichment calls external APIs during CI. Not suitable for air-gapped environments.
- Rate limits: APIs may rate-limit large SBOMs. sbomify uses caching and backoff, but very large dependency trees (1000+ packages) may see slower enrichment.
- Best effort: If a package isn't in any registry (private packages, vendored code), no metadata will be added.
📖 See docs/enrichment_coverage.md for detailed coverage information by ecosystem.
sbomify uses a plugin architecture for SBOM generation, automatically selecting the best generator for each input type and ecosystem.
Generators are tried in priority order. Native tools (optimized for specific ecosystems) are preferred over generic scanners. Each tool supports different ecosystems:
| Priority | Generator | Supported Ecosystems | Output Formats |
|---|---|---|---|
| 10 | cyclonedx-py | Python only | CycloneDX 1.0–1.7 |
| 10 | cargo-cyclonedx | Rust only | CycloneDX 1.4–1.6 |
| 20 | cdxgen | Python, JavaScript, Java/Gradle, Go, Rust, Ruby, Dart, C++, PHP, .NET, Swift, Elixir, Scala, Docker images | CycloneDX 1.4–1.7 |
| 30 | Trivy | Python, JavaScript, Java/Gradle, Go, Rust, Ruby, C++, PHP, .NET, Docker images | CycloneDX 1.6, SPDX 2.3 |
| 35 | Syft | Python, JavaScript, Go, Rust, Ruby, Dart, C++, PHP, .NET, Swift, Elixir, Terraform, Docker images | CycloneDX 1.2–1.6, SPDX 2.2–2.3 |
- Python lockfiles → cyclonedx-py (native, most accurate for Python)
- Rust lockfiles (Cargo.lock) → cargo-cyclonedx (native, most accurate for Rust)
- Java lockfiles (pom.xml, build.gradle, gradle.lockfile) → cdxgen (best Java support)
- Dart lockfiles (pubspec.lock) → cdxgen or Syft (Trivy doesn't support Dart)
- Other lockfiles (package-lock.json, go.mod, etc.) → cdxgen (then Trivy, then Syft as fallbacks)
- Docker images → cdxgen (then Trivy, then Syft as fallbacks)
If the primary generator fails or doesn't support the input, the next one in priority order is tried automatically.
Control the output format with the SBOM_FORMAT environment variable:
- CycloneDX (
SBOM_FORMAT=cyclonedx): Default format. Uses the latest version supported by the selected generator. - SPDX (
SBOM_FORMAT=spdx): Uses Trivy (2.3) or Syft (2.2/2.3) depending on availability.
Generated SBOMs are validated against their JSON schemas before output.
When installed via pip, sbomify-action requires external SBOM generators. The Docker image includes all tools pre-installed.
| Tool | Install Command | Notes |
|---|---|---|
| cyclonedx-py | pip install cyclonedx-bom |
Native Python generator; cyclonedx-py is the CLI command provided by the cyclonedx-bom package (installed as a dependency) |
| Trivy | Installation guide | macOS: brew install trivy |
| Syft | Installation guide | macOS: brew install syft |
| cdxgen | npm install -g @cyclonedx/cdxgen |
Requires Node.js/Bun |
Minimum requirement: At least one generator must be installed for SBOM generation. For Python projects, cyclonedx-bom (which provides the cyclonedx-py command) is installed as a dependency when you install sbomify-action via pip. For other ecosystems or Docker images, install trivy, syft, or cdxgen.
- CycloneDX: 1.3, 1.4, 1.5, 1.6, 1.7 (JSON)
- SPDX: 2.2, 2.3 (JSON)
📖 See docs/adr/0001-plugin-architecture.md for architecture details.
Apache-2.0