A CLI, shipped as a container image, that turns a lock file into a compliance-grade SBOM inside your pipeline. It picks the right generator for your ecosystem, injects packages no lock file knows about, adds your business metadata, and enriches every component from package registries.
It runs as a GitHub Action, as a container image on any other CI, or locally with uvx. Configuration is environment variables and is identical everywhere. Works standalone or with sbomify β generation, augmentation and enrichment need no account.
π Full documentation
Watch our FOSDEM 2026 talk for a real-world crash course on generating CRA-ready SBOMs β covering the full pipeline from authoring to enrichment and signing.
The fastest way to get going is the interactive setup wizard. Run it from the root of your repository:
docker run --rm -it \
-v "$(pwd):/workspace" \
ghcr.io/sbomify/sbomify-action \
sbomify-action wizardIt scans your repository for lock files, signs you in to sbomify, registers the matching components, and writes a release-ready .github/workflows/sboms.yml. Pass --dry-run to preview the plan without making API changes or writing files.
The wizard is interactive, so the -it flags are required, and it must run on your machine rather than in CI. If you would rather not use Docker, uvx sbomify-action wizard does the same thing.
π Quick start guide
- uses: sbomify/sbomify-action@master
env:
LOCK_FILE: requirements.txt
OUTPUT_FILE: sbom.cdx.json
ENRICH: true
UPLOAD: falseThat generates a CycloneDX SBOM from your lock file and enriches it with metadata from package registries. No account required. For SPDX, set SBOM_FORMAT: spdx.
On any other CI, pass the same variables to the container image:
docker run --rm \
-v "$(pwd):/workspace" \
-e LOCK_FILE=requirements.txt \
-e OUTPUT_FILE=sbom.cdx.json \
-e ENRICH=true \
-e UPLOAD=false \
ghcr.io/sbomify/sbomify-actionThe image's working directory is /workspace, so mounting your repository there needs no -w. Any other mount point works too, as long as -w points at it β including an existing -v "$PWD:/github/workspace" -w /github/workspace, which keeps working unchanged. Keep the mount and the -w in step: outputs are written relative to the working directory, so a mount without a matching -w leaves your SBOM inside the container.
π Runtime guides β GitHub Actions, GitLab CI, Bitbucket, Jenkins, CircleCI, Azure DevOps, TeamCity, any container runner, and local
A scanner's job is detection. It gives you a name, a version and a PURL, and leaves supplier, license, description and hashes empty β which are exactly the fields NTIA, CISA and the EU CRA ask for. A raw scan is a dependency list; compliance needs an SBOM.
This tool wraps generation in three more steps β inject, augment, enrich β and runs the whole thing at build time, where the full dependency context exists and the result can be signed at origin.
- Generate from lock files across 17 ecosystems, container images, or a directory, in CycloneDX or SPDX
- Native generators per ecosystem β
cyclonedx-py,cargo-cyclonedx,cyclonedx-gomod,cyclonedx-maven,cyclonedx-gradle,cyclonedx-sbtβ with cdxgen and Syft as fallbacks - Chainguard SBOM reuse β detects Chainguard base images and uses the publisher's SBOM instead of scanning
- Yocto/OpenEmbedded β batch process SPDX SBOMs from Yocto builds
- Inject additional packages not in lock files (vendored code, runtime deps, system libraries)
- Augment with business metadata β supplier, authors, licenses, lifecycle phase β from a local config file or sbomify
- VCS auto-detection on GitHub Actions, GitLab CI, Bitbucket, Jenkins, CircleCI, Travis CI and TeamCity (Git roots only), and from the git checkout itself everywhere else β Azure Pipelines, any other container runner and your own machine.
DISABLE_VCS_AUGMENTATION=trueturns it off - Enrich from PyPI, crates.io, pub.dev, Conan Center, deps.dev, ecosyste.ms and pre-computed distro license databases
- Hashes and lifecycle data β integrity hashes pulled from your lock file, CLE end-of-support dates for OS packages and tracked runtimes
- Audit trail β every modification logged with UTC timestamps, for attestation and compliance
- Upload to sbomify or Dependency Track, tag product releases, attest with GitHub build provenance
- Documents β publish the evidence an SBOM cannot carry (pentest reports, SOC 2 attestations, threat models, declarations of conformity) to the same component and the same release
- Tokenless publishing on GitHub Actions via OIDC trusted publishing
| 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 |
| Haskell | stack.yaml.lock, stack.yaml, cabal.project.freeze |
| Erlang | rebar.lock (rebar3 projects; erlang.mk has no equivalent) |
| Clojure | deps.edn, project.clj |
Naming a manifest that sits beside its lock file reads the lock file instead: package.json defers to package-lock.json, pyproject.toml to poetry.lock.
Container images are supported via DOCKER_IMAGE, and a whole directory via SOURCE_DIR β though a directory scan is a weaker claim than a lock file, so reach for it only when nothing else applies.
π Input sources
- CycloneDX 1.2β1.7 (JSON) β generate and process. Defaults to 1.6; override with
SPEC_VERSION - SPDX 2.2 and 2.3 (JSON) β generate and process. Defaults to 2.3
- SPDX 3.0.1 (JSON-LD) β process only; supply an existing document via
SBOM_FILE
Compliance asks for more than an SBOM. The EU CRA wants a security assessment and a declaration of conformity, SOC 2 and ISO 27001 want their attestation reports, and FDA and PCI DSS name several more. Those are documents, not BOMs β and they belong beside the SBOM they describe rather than in a shared drive somewhere.
Point DOCUMENT_FILE at the file. It is uploaded exactly as authored: nothing is generated,
augmented, enriched or re-serialized, so a signed report stays byte-for-byte the one that was
signed.
- uses: sbomify/sbomify-action@master
env:
TOKEN: ${{ secrets.SBOMIFY_TOKEN }}
COMPONENT_ID: ${{ vars.DOCS_COMPONENT_ID }}
DOCUMENT_FILE: reports/pentest-2026.pdf
DOCUMENT_TYPE: pentest-report
DOCUMENT_VERSION: '2026.1'The component must be of type document in sbomify; a component created for SBOMs (type bom)
cannot hold documents. Locally or on any other CI the same variables work with the container image
and with uvx sbomify-action, and every one of them has a CLI flag (--document-file,
--document-type, β¦).
| Variable | Default | Description |
|---|---|---|
DOCUMENT_FILE |
β | Path to the document. Mutually exclusive with SBOM_FILE / LOCK_FILE / SOURCE_DIR / DOCKER_IMAGE |
DOCUMENT_NAME |
file name without its extension | Name shown in sbomify |
DOCUMENT_TYPE |
other |
See the list below |
DOCUMENT_VERSION |
COMPONENT_VERSION, else 1.0 |
Version recorded for the document |
DOCUMENT_DESCRIPTION |
empty | Free text stored with the document |
DOCUMENT_COMPLIANCE_SUBCATEGORY |
β | nda, soc2 or iso27001; only for DOCUMENT_TYPE: compliance |
PRODUCT_RELEASE tags the uploaded document into a release exactly as it does an SBOM, so a
release can carry its SBOM and its evidence together. OIDC trusted publishing works the same way
too β no token needed on GitHub Actions.
Document types: specification, manual, readme, documentation, build-instructions,
configuration, license, compliance, evidence, changelog, release-notes,
security-advisory, vulnerability-report, threat-model, risk-assessment, pentest-report,
static-analysis, dynamic-analysis, quality-metrics, maturity-report, report, other.
Documents are capped at 50 MB each.
| Topic | |
|---|---|
| Quick start | The wizard, and your first pipeline run |
| Why SBOM quality matters | Scanners vs. pipelines, and chain of custody |
| How it works | The full pipeline, step by step |
| Configuration | Every input, environment variable and CLI flag |
| Input sources | Lock files, container images, directories, Yocto, additional packages |
| Augmentation | Your business metadata via sbomify.json |
| Enrichment | Registry metadata, license databases, lifecycle data, hashes |
| Publishing | OIDC trusted publishing, releases, Dependency Track |
| Advanced | Attestation, audit trail, tool runtimes, caching, troubleshooting |
| Runtimes | Setup for your CI platform |
In this repository:
- Enrichment coverage β expected field coverage per ecosystem
- NTIA comparison β how output maps to the NTIA minimum elements
- Architecture decision records
Tool runtimes. Only cyclonedx-py ships with the package. Syft, cdxgen, the JVM toolchain, Go, Rust, PHP, .NET, crane and cosign are not baked into the image β they are downloaded on first use, verified against a digest pinned at build time, and cached. Set SBOMIFY_TOOL_CACHE to persist that cache across CI runs, or SBOMIFY_FETCH_RUNTIMES=0 to opt out for air-gapped builds. See tool runtimes.
Trivy is currently not shipped, after compromised releases in March 2026. The remaining generators cover every supported ecosystem.
Pinning. Examples here use @master so they stay correct as the action moves. Do not ship that: pin to a release tag, or for production to a full 40-character commit SHA β see SECURITY.md. The wizard does this automatically for the workflows it generates.
Report vulnerabilities to security@sbomify.com. See SECURITY.md for scope, response targets and hardening guidance.
Apache-2.0