Guide · SBOM

Make an SBOM for your stack

A software bill of materials lists the components inside what you ship, with their versions. The Cyber Resilience Act expects manufacturers to keep one (Annex I Part II(1)). Free open-source tools produce one for every common stack in a few minutes. This page gives the command for each, and what to check before you rely on the result.

The tools below belong to their own projects; SkyQon does not make or support them. Commands checked against each project's documentation on 13 November 2026.

Before you start

  • Pick one format. CycloneDX and SPDX are the two open standards. Both work. SkyQon reads CycloneDX JSON and SPDX 2.x JSON; it does not read XML or SPDX 3.0 yet.
  • Describe what you ship, not your laptop. Run the tool on the release build, the lock file or the image you deliver. An SBOM made from a developer machine lists test tools and leaves out what the build adds.
  • One SBOM per version. Make a new one for every release and keep the old ones. A vulnerability report names a version; the SBOM for that version is what tells you whether it is yours.
  • Make it part of the build. Every command below runs without prompts, so it fits in a CI step next to the build that produces the release.

Any stack and containers

Two general tools read most package managers and container images. Start here if your product mixes languages or ships as an image.

Syft

Scans a directory or a container image and writes both formats at once.

syft ./my-product -o cyclonedx-json=./sbom.cdx.json
syft registry.example.com/acme/app:2.1.0 -o spdx-json=./sbom.spdx.json

Trivy

Scans an image or a project folder. With this format the output holds components only, not vulnerability results.

trivy image --format cyclonedx --output sbom.cdx.json acme/app:2.1.0
trivy fs --format cyclonedx --output sbom.cdx.json ./my-product

cdxgen

Detects the languages in a project folder by itself; add a type when it guesses wrong.

npm install -g @cdxgen/cdxgen
cdxgen -o sbom.cdx.json .
cdxgen -t java -o sbom.cdx.json .

By language

Each ecosystem has a CycloneDX tool that reads its own lock file. These see the exact versions the build resolved.

Python

From the environment the release runs in, or from a requirements file. JSON is the default output.

pip install cyclonedx-bom
cyclonedx-py environment --output-file sbom.cdx.json
cyclonedx-py requirements requirements.txt --output-file sbom.cdx.json

JavaScript (npm)

Built into the npm command line in current versions. Leave development dependencies out of what you ship.

npm sbom --sbom-format=cyclonedx --omit=dev > sbom.cdx.json
npm sbom --sbom-format=spdx --omit=dev > sbom.spdx.json

Java

Maven runs the CycloneDX plugin without editing the project and writes bom.json under target. For Gradle, add the plugin org.cyclonedx.bom to the build and run its task; the file lands in build/reports/cyclonedx.

mvn org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom
./gradlew cyclonedxBom

Go

The app mode follows the same build settings as your release, so set them the way your build does.

go install github.com/CycloneDX/cyclonedx-gomod/cmd/cyclonedx-gomod@latest
GOOS=linux GOARCH=amd64 cyclonedx-gomod app -json -output sbom.cdx.json -main cmd/app .

Rust

Run in the folder that holds Cargo.toml. The file is written next to it.

cargo install cargo-cyclonedx
cargo cyclonedx --format json

.NET

cdxgen reads the project and lock files. The CycloneDX .NET tool is the other common choice.

cdxgen -t dotnet -o sbom.cdx.json .

C, C++ and embedded Linux

C and C++

There is no single package list, so expect gaps. cdxgen reads common C and C++ build metadata; libraries copied into the source tree are often missed and need adding by hand. For firmware, also scan the finished image with Syft and compare.

cdxgen -t c -o sbom.cdx.json .

Yocto

Current releases write an SPDX file for every image build by default, in tmp/deploy/images/MACHINE/ named IMAGE-MACHINE.spdx.json. Older releases write SPDX 2.2, which SkyQon reads. Newer releases write SPDX 3.0, which SkyQon does not read yet: run Syft on the image root filesystem to get a CycloneDX file instead.

bitbake core-image-minimal
ls tmp/deploy/images/*/*.spdx.json

Check it before you trust it

  • Count the components. A web service with a handful of entries is almost always a scan of the wrong folder. Compare the count with your lock file.
  • Look for package URLs. Matching against vulnerability databases works on the package URL (purl) or the CPE of each component. Entries with a name and nothing else cannot be matched.
  • Find your own product at the top. The SBOM should name your product and its version as the main component, so a reader knows which release it describes.
  • Spot the test tools. Linters, test frameworks and build plugins in the list mean it was made from a development setup, not from the release.

Hand it to SkyQon

With the CRA Product Evidence add-on, upload the file on the product's page and name the version. SkyQon reads up to 20,000 components from a file of up to 20 MB, keeps every version, and checks the components every day against OSV.dev and the NVD, with CISA KEV and EPSS added to each match. Only package identifiers leave the platform; the file itself stays with your evidence.

A match is a lead, not a verdict: you record whether it affects you, and that record goes into the signed product evidence report. Not legal advice; the manufacturer remains responsible for the SBOM and what it shows.

Not sure the CRA covers your product?

The free scope and class check takes about ten minutes per product and cites the articles behind each answer.