• SBOM
  • comparisons
  • Syft

SBOM tools compared: Syft, Trivy, Docker Scout, cdxgen and cluster-level SBOMs

Syft, Trivy, Docker Scout and cdxgen compared: the current command for each, where each is best, and why an SBOM of what your cluster runs needs a different tool.

StackRadar Team

8 min read

For container images, SBOM generation is a solved problem: Syft or Trivy, or something that wraps one of them. The choices that actually change your results are elsewhere. Do you generate from the build or from the image? And do you want an SBOM of one image you name, or of everything your cluster is running right now?

The short answer, by job:

  • One container image: Syft.
  • You already run Trivy in CI: Trivy, and take the SBOM as a by-product.
  • You live in Docker Desktop or Docker Hub: docker scout sbom. The old docker sbom has been removed.
  • An application source tree: cdxgen, or your package manager's CycloneDX plugin.
  • Images you build yourself: BuildKit SBOM attestations, attached at build time.
  • Everything running in a cluster: a cluster-level tool. None of the generators does this on its own.

Syft: the reference image generator

Syft (Anchore, Apache-2.0) reads an image, a directory or an archive. It runs a set of catalogers (apk, dpkg, rpm, npm, pip, Go modules, Java archives, Rust, Ruby, PHP, .NET, binaries and more) and emits CycloneDX, SPDX or its own JSON.

bash
syft registry:docker.io/library/nginx:1.27-alpine --platform linux/amd64 \
  -o cyclonedx-json@1.6 > nginx.cdx.json

That exact command produced the downloadable example on our CycloneDX page: 68 Alpine packages, one operating-system component, 62 dependency records, and 978 file entries recording binary evidence. The registry: prefix pulls straight from the registry without a Docker daemon, and @1.6 pins the CycloneDX spec version so downstream tools get the version they expect.

Syft is also the generator inside the StackRadar scanner, unmodified. We did not write our own: its cataloger coverage is broader than anything we would have built, and its output is what every matcher already reads. Credit to Anchore for maintaining it in the open.

Best for: any container image, and converting between formats. Limits: it inspects the artefact, so it sees what was installed, not the dependency graph the build resolved. A jar that shades its dependencies can show up as one component, not fifty. Pair it with Grype, from the same maintainers, to turn the SBOM into vulnerability findings.

Trivy: an SBOM from the scanner you already run

Trivy (Aqua Security, Apache-2.0) is primarily a vulnerability scanner, but --format cyclonedx or --format spdx-json turns any scan into an SBOM. trivy sbom then scans an SBOM that Trivy or Syft produced.

bash
trivy image --platform linux/amd64 --format cyclonedx \
  --output nginx.cdx.json nginx:1.27-alpine

With --format cyclonedx, Trivy writes the inventory only. Add --scanners vuln if you want vulnerabilities embedded in the same document. Coverage of OS packages is comparable to Syft's, but expect different component counts on the same image: the catalogers differ, and so do their opinions about what counts as a "package" inside a Go binary.

Best for: teams that already run Trivy in CI and want an SBOM with no extra tool. Pin the version or image digest you install: Trivy's release binaries, images and trivy-action tags were briefly compromised in March 2026 (GHSA-69fq-xp46-6x23). In-cluster, Trivy Operator writes the same documents as SbomReport resources (see below).

docker sbom (removed) and docker scout sbom

docker sbom arrived as an experimental CLI plugin in 2022 and was a thin wrapper around Syft. Docker has since deprecated it: the plugin's repository was archived in May 2026 and its README says the command has been removed. Scripts that still call it need migrating.

The replacement is docker scout sbom, part of Docker Scout and bundled with Docker Desktop. It reads local images, registry images, OCI directories and docker save archives, and outputs Scout's own JSON, SPDX, CycloneDX or a plain package list.

bash
docker scout sbom --platform linux/amd64 --format cyclonedx \
  --output nginx.cdx.json nginx:1.27-alpine

Best for: teams already using Scout for image analysis in Docker Desktop or Docker Hub. Outside that ecosystem, Syft gives you the same kind of document from a standalone binary with no Docker tooling involved.

cdxgen: the build-time generator

cdxgen (OWASP CycloneDX, Apache-2.0) starts from source. Point it at a repository and it resolves the dependency graph through the package manager (npm, Maven, Gradle, pip, Go, .NET and many more), producing CycloneDX with the full transitive tree, scopes and evidence.

bash
cdxgen -t js -o bom.json ./checkout-service

For application code it is usually more complete than an image inspection, because it sees what the build resolved rather than what survived into the artefact. It can scan images too (-t docker), but that is not its strength, and it can be slow or fragile on builds that need a specific toolchain installed.

Best for: application SBOMs for licence, provenance and supply-chain review.

Build SBOM or image SBOM

This is the real choice in the whole field. A build SBOM knows about devDependencies and build tools. An image SBOM knows about glibc and OpenSSL. To track vulnerabilities in production, the image SBOM is the one that matters, because the image is what the kubelet runs. The build SBOM answers licence and provenance questions. Many teams keep both and attach them to the image as attestations.

STAGESBOM FROMWHAT IT KNOWSBuildresolves thesource treeImagewhat thekubelet runsBuild SBOMcdxgen, package-manager pluginsImage SBOMSyft, TrivyFull transitive dependency treedevDependencies and build toolsAnswers licence and provenanceOS packages — glibc, OpenSSLWhat actually shippedTracks vulnerabilities in production

Other SBOM generators you will meet

  • BuildKit attestations: docker buildx build --sbom=true attaches an SPDX SBOM (Syft-based by default) to the image manifest as an in-toto attestation. Worth doing for every image you build. It does nothing for the images you pull.
  • Tern: layer-by-layer container inspection from the Linux Foundation. Its per-layer attribution is unusual, but it has not had a release since July 2023.
  • Language-native plugins: the CycloneDX Maven, Gradle and npm plugins, cargo cyclonedx, and pip-audit's CycloneDX output. Precise for one ecosystem, blind to everything else.
  • Commercial scanners (Snyk, Sysdig, Wiz and others) all export an SBOM. That is fine as a by-product, but it is rarely the reason to pick one.

The cluster-level SBOM is a different tool

Every tool above takes an artefact you name and describes it. A cluster is not an artefact. It is a set of image digests that changes with every deploy, and many of them are images nobody in your organisation built: ingress controllers, operators, CNI plugins, monitoring agents. A cluster-level SBOM tool has three jobs the generators do not do:

  1. Discover the digests the kubelets are actually running, including init containers and injected sidecars, and notice when they change.
  2. Generate once per digest, however many pods share it, with credentials that reach your private registries.
  3. Keep and attribute the result: one dated SBOM per image per cluster, tied to the namespaces, workloads, Helm releases and ArgoCD applications that run it, and superseded rather than overwritten when the digest changes.

In the example below, seven pods (an illustrative count) share three digests, so the tool produces three SBOMs.

IN THE CLUSTERONCE PER DIGESTOVER TIMEDiscoverrunning digests: app,init and sidecarsGenerateonce per digest, withregistry credentialsKeep and attributeone dated SBOM per image,tied to what runs itcheckout — 3 pods1 SBOM · checkoutNamespace and workloadproxy sidecar — 3 pods1 SBOM · proxyHelm releasemigrate init — 1 pod1 SBOM · migrateArgoCD application

Trivy Operator covers discovery and generation. It scans each workload with the workload's own pull secrets and writes an SbomReport custom resource next to it. Those reports live in the cluster's etcd, get replaced on each rescan (vulnerability reports expire after 24 hours by default, which triggers one), and are deleted along with the workload. For one cluster where you only care about now, that is a reasonable answer. The StackRadar vs Trivy Operator post compares the two in detail.

StackRadar does all three jobs with Syft inside its scanner. It generates once per digest, pulls with registry credentials you configure (or, opt-in, the pull Secrets your pods already declare), and keeps the SBOMs outside the cluster. You can download each image's SBOM, and it is re-matched as new advisories land.

Building it yourself from Syft, a CronJob and Dependency-Track is also a legitimate path. Generating the SBOM is the easy part. Discovery, per-digest deduplication and attribution are where the work is.

Whatever tool you pick, set the platform your nodes run (--platform linux/amd64, or linux/arm64 on Graviton or Ampere nodes). For multi-arch images, Syft and Trivy default to the host's platform, so an SBOM generated on an Apple Silicon laptop describes an arm64 image your amd64 cluster never runs.

SBOM tools side by side

ToolInputFormatsOS packagesFull dependency graphWhole cluster
SyftImage, directory, archiveCycloneDX, SPDX, Syft JSONYesPartial (what is installed)No
TrivyImage, filesystem, repoCycloneDX, SPDXYesPartialVia Trivy Operator
docker scout sbomImage, directory, archiveCycloneDX, SPDX, Scout JSONYesPartialNo
cdxgenSource tree, imagesCycloneDXYes, from imagesYes, from sourceNo
BuildKit attestationsYour own buildsSPDXYesPartialNo
Trivy OperatorRunning clusterCycloneDX (CRD)YesPartialOne cluster, replaced on rescan
StackRadarRunning cluster(s)CycloneDX 1.6 (Syft)YesPartialEvery cluster, history kept

Choosing between CycloneDX and SPDX is a separate question with a shorter answer: CycloneDX vs SPDX covers it.

To see cluster-level SBOMs without building the pipeline yourself, open the live demo: every image on the sample cluster has its SBOM and its findings, and it needs no account.

Frequently asked questions

How do I generate an SBOM for a container image?

Run Syft against the image reference: `syft nginx:1.27-alpine --platform linux/amd64 -o cyclonedx-json > sbom.json`, or `-o spdx-json` for SPDX. Syft pulls from the registry with your existing credentials and needs no Docker daemon. If Trivy is already installed, `trivy image --format cyclonedx --output sbom.json nginx:1.27-alpine` does the same job.

What is the best SBOM generation tool?

It depends on the input. For a container image, Syft: the broadest set of package catalogers, and the generator most other tools wrap. For an application source tree, cdxgen, because it resolves the full dependency graph from the package manager. For every image running in a Kubernetes cluster, you need a tool that discovers the running digests and runs a generator per image, such as Trivy Operator or StackRadar.

What is the difference between Syft and Grype?

Syft generates an SBOM: the inventory of packages in an image or directory. Grype reads an SBOM (or an image directly) and matches those packages against vulnerability databases. Both are open source from Anchore. Generate the SBOM with Syft once per image, then re-run Grype on it whenever the vulnerability database updates.

Does docker sbom still work?

No. Docker deprecated the `docker sbom` plugin, which wrapped Syft, and archived its repository in May 2026; the README now says the command has been removed. The replacement is `docker scout sbom`, which ships with Docker Desktop and outputs CycloneDX or SPDX. If your scripts call `docker sbom`, switch them to `docker scout sbom` or to Syft.

Should the SBOM come from the build or from the image?

They answer different questions, and many teams keep both. A build-time SBOM (cdxgen, a package-manager plugin) has the full resolved dependency graph, including devDependencies and build tools, which is what licence and provenance reviews need. An image SBOM (Syft, Trivy) records what actually shipped, including OS packages such as glibc and OpenSSL. To track vulnerabilities in production, use the image SBOM: the image is what the kubelet runs.

All posts