Express + expert help

View pricing →
Skip to main content
referenceCRA14 min read

SBOM tooling for embedded systems: Syft, Trivy, Yocto SPDX and CycloneDX-generators compared

SBOM tools for embedded development compared — Syft, Trivy, Yocto create-spdx, CycloneDX-generators, EMBA — with a decision matrix and CRA Annex I Part II mapping.

By Vladimír VicianUpdated

The Cyber Resilience Act (Regulation (EU) 2024/2847) ties a manufacturer's vulnerability handling obligation to the existence of an accurate, machine-readable SBOM. Annex I Part II requires manufacturers to identify and document vulnerabilities and components contained in the product, and the Commission's CRA policy page treats the SBOM as the operational backbone of that duty. For embedded teams the practical question is which tools to actually run — and which combination produces an SBOM that survives a market surveillance request.

This article compares the major SBOM toolchains for embedded development across two axes: build-time generation versus binary scanning, and SPDX versus CycloneDX format support. It pairs each tool with its honest limitations and maps each option to the CRA Annex I Part II requirement language. For cadence rules see our SBOM update frequency guide; for the format-level choice see CycloneDX vs SPDX for hardware; for the harder case of legacy binaries see the companion article on SBOM from legacy embedded firmware.

Two workflows that fit different teams

The fundamental decision is whether your SBOM comes from the build or from the binary.

Build-time SBOM is generated by the same toolchain that produces the firmware artifact. The build system already knows every recipe, every source URL, every patch applied, every license and every version. The SBOM is exact, the manifest is complete, and the generation runs in CI alongside compilation. This is the gold standard. Yocto's create-spdx class, Buildroot's manifest export and language-specific CycloneDX generators (cyclonedx-python, cyclonedx-node-npm, cyclonedx-go) all sit in this category.

Binary-scan SBOM is generated by analysing the produced binary or its packaged form. The scanner reads package-manager databases (apk, dpkg, RPM) inside container or root filesystems, inspects language-specific manifests (composer.lock, package-lock.json, go.sum, requirements.txt) found in source trees, and uses heuristics for stripped binaries. The output is inferred — accurate for what the scanner can see, silent on what it cannot. Syft and Trivy lead this category. They are essential when you did not build the artifact yourself.

Most production embedded programmes need both. Build-time tools cover everything you control; binary scanners catch third-party modules, vendor firmware blobs and historical artifacts.

Build-time tools

Yocto/OpenEmbedded — create-spdx

Yocto's create-spdx class is the most complete build-time SBOM generator for embedded Linux. Per the Yocto documentation:

"The OpenEmbedded build system generates such information by default (by inheriting the create-spdx class in INHERIT_DISTRO)."

The output is an SPDX JSON document — IMAGE-MACHINE.spdx.json — containing components, licenses, dependencies, sources, the changes applied to each component, and the known vulnerabilities that were fixed. Supplementary classes extend coverage:

  • cargo_common — Rust crates
  • go-mod — Go modules
  • pypi — Python packages
  • npm — Node.js packages
  • cpan* — Perl modules

Strengths: complete dependency graph from the same recipes that build the binary; exact licence and version data; native SPDX output that maps to ISO/IEC 5962:2021; well-integrated with Yocto's existing CVE checker.

Limitations: SPDX only — no native CycloneDX output (you must convert downstream); requires the build to actually run through Yocto, not a black-box vendor SDK; updates require a rebuild.

Buildroot — manifest exports

Buildroot does not ship a single-class SBOM generator, but make legal-info produces a manifest of packages, versions, licenses and source URLs. Third-party converters (e.g. buildroot-cyclonedx) turn the manifest into a CycloneDX BOM. For Buildroot-based products, the manifest-plus-converter approach is the closest analogue to Yocto's create-spdx.

Language-specific CycloneDX generators

For code that isn't built through a top-level integration system, the OWASP CycloneDX project maintains per-ecosystem generators:

  • cyclonedx-python — generates CycloneDX from Python requirements and Poetry/Pipenv/PDM lock files
  • cyclonedx-node-npm — generates CycloneDX from npm/pnpm/yarn lockfiles
  • cyclonedx-go — generates CycloneDX from go.mod and go.sum
  • cyclonedx-bom — generic .NET, Java/Maven and Gradle generators
  • cyclonedx-rust-cargo — generates CycloneDX from Cargo.lock

All emit CycloneDX 1.7 JSON or XML out of the box.

Filesystem and image scanners

Syft (Anchore)

Syft is a CLI and Go library purpose-built for SBOM generation. Its README describes the tool as generating "SBOMs for container images, filesystems, archives" and notes support for signed SBOM attestations via the in-toto specification.

Format support:

  • CycloneDX (JSON, XML, Protocol Buffers — matching the ECMA-424 specification)
  • SPDX (JSON, tag-value)
  • Syft's own JSON format
  • Conversion between formats

Ecosystem coverage:

  • Linux package managers: Alpine (apk), Debian (dpkg), RPM
  • Language ecosystems: Go, Python, Java, JavaScript, Ruby, Rust, PHP, .NET and others
  • Targets: container images (OCI, Docker, Singularity), filesystems, archives

Strengths: deep ecosystem coverage; clean SBOM-only focus; high-quality CycloneDX and SPDX output; pairs natively with Grype for downstream vulnerability matching.

Limitations: does not detect statically-linked code in stripped binaries; does not natively understand a vendor firmware blob — you must extract the filesystem first.

Trivy (Aqua Security)

Trivy is a multi-scanner that produces SBOMs alongside other security findings. Its target list is broader than Syft's:

  • Container images
  • Filesystems
  • Git repositories (remote)
  • Virtual machine images
  • Kubernetes clusters

Scanning capabilities include OS packages and software dependencies (with SBOM generation), known CVEs, infrastructure-as-code misconfigurations, sensitive information and secrets, and software licenses. SBOM output supports both CycloneDX and SPDX.

Strengths: one tool, multiple workflows; built-in CVE matching; broad target coverage including VM images; tight CI integration.

Limitations: SBOM emission is one of many features, not the primary focus; same binary-blob limitation as Syft.

Comparison

CapabilitySyftTrivy
SBOM is the primary focus✅Secondary capability
CycloneDX output✅✅
SPDX output✅✅
Container image scanning✅✅
Filesystem scanning✅✅
VM image scanningLimited✅
Git repo scanning✅✅
Kubernetes scanningVia integrations✅ Native
Signed SBOM attestations✅ (in-toto)Limited
Native CVE matchingVia Grype✅
IaC misconfiguration scanning❌✅
Secret detection❌✅

For pure SBOM emission, Syft is the more focused tool. For a single CI step that produces SBOM plus CVE plus secret plus IaC findings, Trivy reduces tool count.

Firmware-specific tooling

When you have a vendor-shipped firmware blob with no source build available, filesystem scanners need help. The two main tools are Binwalk and EMBA.

Binwalk

Binwalk was rewritten in Rust for speed and accuracy. Per the README:

"Binwalk can identify, and optionally extract, files and data that have been embedded inside of other files."

It identifies a wide variety of file types, includes entropy analysis to flag compressed or encrypted regions, and supports embedded-filesystem extraction. Latest stable release at the time of this article is v3.1.0 from 31 October 2024.

Binwalk does not produce an SBOM by itself. It produces the inputs (extracted filesystems) that Syft or Trivy can then scan.

EMBA

EMBA is a firmware-analysis platform that orchestrates the full pipeline: extraction, static analysis, optional dynamic analysis via emulation, and vulnerability reporting. It detects insecure binaries, outdated software components, vulnerable scripts and hard-coded credentials. It produces SBOMs via dedicated scan profiles — including the default-sbom.emba profile.

EMBA's strength is orchestration. For a firmware blob where you do not know what extraction tool to run, what scanner to apply, or how to chain the steps, EMBA produces a defensible analysis output without manual choreography.

Explore Cenitia’s compliance workflow

Review the supported scope and workflow

SBOM format choice — SPDX or CycloneDX

CRA Annex I Part II requires the SBOM in "a commonly used and machine-readable format covering at the very least the top-level dependencies of the products". Two widely used candidate formats are; validate the chosen document, dependencies and tool interoperability:

  • SPDX — governed by the Linux Foundation, with SPDX 2.2.1 published as ISO/IEC 5962:2021; this does not make every subsequent SPDX edition the same ISO publication. The SPDX 3 family includes SPDX 3.0.1, with SPDX 2.3 (August 2022) still in wide use.
  • CycloneDX — governed by the OWASP Foundation and Ecma International (ECMA-424). Current release: CycloneDX 1.7, with the ECMA-424 publication date of 10 December 2025. Formats: JSON (application/vnd.cyclonedx+json), XML (application/vnd.cyclonedx+xml) and Protocol Buffers.

A detailed format comparison sits in CycloneDX vs SPDX for hardware. The summary: SPDX is the more mature legal/licence-focused format with deep ISO standing; CycloneDX is the more vulnerability- and supply-chain-focused format with native support for HBOM (Hardware BOM), SaaSBOM and cryptographic asset transparency. Neither format name alone proves that an SBOM meets the CRA requirement. Pick the one your downstream platform (Anchore, Dependency-Track, Aqua, vendor portal) consumes most easily.

Honest residual gaps

Every SBOM tool we have discussed has a known limitation. A truthful CRA programme acknowledges them.

  • Statically-linked code is invisible to package-manager-based scanners. If a vendor compiled OpenSSL directly into their proprietary binary, neither Syft nor Trivy will see it. Workarounds: Yocto's create-spdx (which knows the recipe), source-level CycloneDX generators, or string-matching scanners (less reliable).
  • Stripped binaries have lost their symbol table. Heuristic detection by symbol fingerprinting fails. EMBA and Binwalk's extraction help, but pure symbol-free binaries remain opaque.
  • In-house libraries with no package-database entry appear as unknown. The SBOM honest-records them but cannot version-match them against any CVE database.
  • Firmware blobs from third-party modules (Wi-Fi, BT, cellular SoCs) are typically signed and encrypted. You cannot extract them, so they appear in the SBOM as a single sealed component with whatever metadata the supplier provides — often nothing.
  • Yocto's SBOM covers what Yocto knows. Out-of-tree kernel modules, vendor SDK binaries pulled in late in the build, or post-build manual additions can escape create-spdx unless explicitly recipe-d.

A CRA Annex I Part II programme must therefore include a documented residual-risk statement: which components could not be enumerated, why, and what compensating monitoring is in place.

Putting it together — a reference embedded SBOM pipeline

For a Yocto-based connected radio product:

  1. CI build — pin the Yocto release and layer revisions. Follow that release’s SBOM documentation; where explicit enablement is needed, the documented configuration is INHERIT += "create-spdx". Some distributions inherit it already. Inspect the actual output format, image binding and completeness rather than assuming a universal SPDX version.
  2. Format conversion — only convert if required by the recipient. Pin the converter and verify which input/output versions it supports. Validate the resulting schema, component identities, relationships and information loss; do not assume it emits CycloneDX 1.7.
  3. Cross-check — Syft scans the final image rootfs and reports any components Yocto missed (vendor SDK binaries, out-of-tree modules). Any gap is investigated and resolved at the recipe level, not papered over.
  4. Vulnerability matching — Grype matches the supported SBOM against its configured vulnerability database; record the database build and advisory sources. OWASP Dependency-Track consumes the CycloneDX SBOM for portfolio-wide CVE correlation.
  5. Artifact storage — SPDX + CycloneDX SBOMs stored in the same artifact repository as the firmware binary, with a checksum binding each SBOM to the exact image hash.
  6. Distribution — Customer-facing SBOM URL on the support page where appropriate (Annex II information requirements and the Article 13 user-information duties shape what the manufacturer must publish; the SBOM itself is typically shared with notified bodies and market surveillance authorities, with a customer-facing summary).

For a vendor-blob-based product where you do not control the build, the pipeline collapses to: Binwalk + EMBA extract → Syft + Trivy scan → residual-risk statement → distribution. The SBOM is honest but partial; a residual-risk statement documents the remaining gap; it does not itself satisfy a missing mandatory SBOM or vulnerability-handling requirement.

Common mistakes

  • Generating only one SBOM "for compliance" and forgetting it. The SBOM is a working artifact for vulnerability handling, not a paper deliverable. If you cannot regenerate it from your CI, you cannot satisfy Annex I Part II.
  • Treating Syft and Trivy as equivalent. They overlap heavily but Syft is SBOM-first, Trivy is multi-scanner. Pick by use case.
  • Skipping the build-time path when Yocto is available. A Yocto build with create-spdx produces a far more complete SBOM than any binary scan. Use binary scanners as a backstop, not as the primary source.
  • Forgetting language-ecosystem coverage. A Yocto SBOM may miss Python packages installed at runtime, or Go modules in a sidecar binary. Pair build-time SBOM with per-ecosystem generators where needed.
  • Picking a format your downstream stack does not support. Anchore Enterprise consumes SPDX natively; OWASP Dependency-Track is CycloneDX-native. Choose the format that matches your platform, then convert for redistribution.
  • Skipping the residual-risk statement. No SBOM is complete for a real-world embedded product. The compliance posture is "here is what we found, here is what we could not enumerate, here is how we monitor the gap". Pretending the SBOM is complete is worse than acknowledging the gap.

Using Cenitia for this work

Cenitia helps prepare evidence-linked working drafts within its supported regulatory catalogue. Confirm the product scope, actual applied standards and completed assessments, and review the result before issuance. Source-change alerts prompt a review; they do not certify conformity, automatically reissue a signed declaration or guarantee monitoring of every national rule and standard edition.

Explore Cenitia’s compliance workflow

Review the supported scope and workflow

Further reading

Last reviewed: 5 July 2026. Cited tools and standards watched continuously by Cenitia — when a new format release or major tool change lands, this article is flagged for update.

FAQ

Frequently asked questions

  • Which SBOM format does the CRA require — SPDX or CycloneDX?

    Neither, by name. CRA Annex I Part II requires an SBOM in 'a commonly used and machine-readable format covering at the very least the top-level dependencies of the products'. The two formats universally accepted as satisfying that wording are SPDX (ISO/IEC 5962:2021) and CycloneDX (ECMA-424). Both are open standards, both have a strong ecosystem of tooling, and both are accepted by the major vulnerability and licence platforms. The choice between them is a tooling-fit decision, not a regulatory one.

  • What is the difference between Syft and Trivy for embedded SBOM work?

    Syft (Anchore) is purpose-built for SBOM generation. It supports CycloneDX, SPDX and Syft JSON output, scans dozens of package ecosystems including Linux package managers (apk, dpkg, RPM) and most language ecosystems, and supports signed SBOM attestations via the in-toto specification. Trivy (Aqua Security) is a multi-scanner: it produces SBOMs but also scans the same target for CVEs, infrastructure-as-code misconfigurations, secrets and licence issues. For pure SBOM emission on an embedded rootfs, Syft is the cleaner tool; for combined vulnerability + SBOM workflows, Trivy reduces the number of tools to run.

  • Can I generate an SBOM directly from a Yocto build?

    Yes. Yocto/OpenEmbedded has a built-in 'create-spdx' bbclass. The OpenEmbedded build system generates an SPDX SBOM by default by inheriting create-spdx in INHERIT_DISTRO. The output is a JSON file named IMAGE-MACHINE.spdx.json. Supplementary classes (cargo_common, go-mod, pypi, npm, cpan*) extend coverage for language-specific ecosystems. The build-time SBOM is the gold standard because it is generated from the same recipes that build the binary, so the dependency graph is complete and accurate without inference.

  • Why do binary-scan SBOM tools miss things?

    Three reasons. First, statically-linked code does not advertise itself the way a package manager record does — the compiler has merged it into a flat ELF. Second, stripped binaries have lost their symbol table, so heuristic detection by symbol fingerprinting fails. Third, custom or in-house libraries that are not in any package database show up as unknown. EMBA, Syft and Trivy all have honest limitations on binary-only scanning — the right answer is to generate the SBOM at build time where possible and use binary scanners as a backstop for third-party components you did not build.

  • Do I need separate tools for containers and bare-metal embedded firmware?

    Often yes. Container images have a well-defined layer + package-database structure that Syft and Trivy parse natively. Bare-metal embedded firmware blobs typically need extraction first — Binwalk to identify and extract the embedded filesystem, then Syft or Trivy on the extracted rootfs, with EMBA orchestrating the whole pipeline. If your embedded device boots a Yocto- or Buildroot-built image, the cleanest path is build-time SBOM from those tools and a binary scan only as cross-check.

  • How often do I need to regenerate the SBOM?

    Every change to the shipped binary that adds, removes or upgrades a component requires a fresh SBOM. CRA Annex I Part II ties SBOM upkeep to the vulnerability handling process — see our companion article on SBOM update frequency under the CRA. The practical rule: regenerate the SBOM in the same CI pipeline that produces the firmware artifact, and store the SBOM alongside the artifact with a checksum binding.

Continue reading

Related guides

Put this into practice

Free tools & references

New to the terminology? Browse the compliance glossary — plain-English, citation-backed definitions of every term above.