P.K. SHARMA

Cyber security intelligence, AI governance, practitioner analysis

Three SBOM tools scanned the same projects and disagreed. CRA compliance cannot be a generator checkbox

A study of 2,050 JavaScript and 1,276 Rust projects found large, systematic differences between Syft, Trivy and cdxgen. The most damaging assumption may be that a valid SBOM file is a complete software inventory.

By Parminder Kumar Sharma · · 5 min read

An engineer compares three conflicting software component manifests beside a dependency graph.

The same repository did not produce the same inventory

A new empirical SBOM tool study tested Syft 1.38.2, Trivy 0.68.2 and cdxgen 12.0.0 against 2,050 JavaScript projects and 1,276 Rust projects. The researchers froze dependency resolution, used lockfiles as a reference and normalised naming differences before comparing coverage.

In the deeper lockfile campaign, cdxgen reported 98.72% of JavaScript packages and 99.34% of Rust packages. Syft reported 43.78% for JavaScript and 100% for Rust. Trivy reported 32.71% for JavaScript and 83.85% for Rust. When no lockfile was available, Syft and Trivy produced empty SBOMs in both ecosystems. cdxgen tried to install JavaScript dependencies, but on Rust it reported only a small portion of the lockfile baseline.

This is not a ranking for every language, build system or deployment artefact. It is a controlled result for stated tool versions, JavaScript and Rust, using lockfiles as the ground truth. Its importance lies elsewhere: all three tools can emit a syntactically valid SBOM while encoding materially different views of the same software.

Average dependency coverage in the study's clean_deep campaign

GeneratorJavaScriptRustKey observation
cdxgen 12.0.098.72%99.34%Highest coverage in both studied ecosystems, with residual directory exclusions
Syft 1.38.243.78%100%Large ecosystem-dependent inversion
Trivy 0.68.232.71%83.85%Lowest JavaScript coverage and incomplete Rust coverage
No lockfileSyft and Trivy emptySyft and Trivy emptyA valid run can still yield no dependency inventory

Most disagreement came from rules, not random failure

The researchers traced differences to dependency scope, discovery source, names, provenance and graph representation. Development dependencies might be included for one package manager and excluded for another. Aliases, peer-dependency suffixes and vendor paths can make the same dependency appear under different identifiers. Monorepos and additional lockfiles change which graph a scanner sees. cdxgen's residual gap included a hard-coded exclusion for directories named examples, which silently skipped lockfiles below that path.

Some behaviours are defects. Others are defensible choices made in the absence of a canonical rule. That is the harder compliance problem. Re-running the same tool may reproduce the same result without proving the result covers the product that is actually shipped. A procurement team may receive two compliant-looking CycloneDX files and be unable to tell that one omits most JavaScript dependencies.

Field completeness also diverged

Field in clean_deep outputcdxgenSyftTrivy
Supplier, both ecosystems0%0%0%
Licences, JavaScript75.8%60.2%0%
Hashes, JavaScript98.2%0%0%
External references, Rust0%97.5%0%
Strict SBOM author, both ecosystems100%0%0%

What the Cyber Resilience Act actually requires

The EU Cyber Resilience Act applies in full from 11 December 2027. Annex I requires manufacturers to identify and document vulnerabilities and components, including an SBOM in a commonly used, machine-readable format covering at least the product's top-level dependencies. Technical documentation must include the SBOM and describe architecture and vulnerability-handling processes.

The regulation sets a minimum legal floor, not a claim that every transitive dependency must always appear in every SBOM. But manufacturers still need enough inventory to operate vulnerability handling, assess third-party components and support the conformity case for the product. A file that covers the formal minimum yet omits dependencies needed for risk management can leave the wider evidence pack weak. The Commission can also specify SBOM format and elements through implementing acts.

The practical control is to define the product boundary before choosing the generator. The inventory target might be a source repository, resolved build graph, container image, firmware bundle or shipped installation. Those are different objects. One scanner invocation rarely proves all of them.

Take this with you

Turn SBOM generation into a controlled evidence process

  • Name the shipped product, version, build and artefact that the SBOM represents
  • Record generator name, version, configuration, ecosystem and generation context
  • Preserve manifests, lockfiles and build metadata used as inputs
  • Test coverage against the package manager and at least one independent inventory source
  • Define whether development, optional, peer, workspace and vendored dependencies are in scope
  • Fail the pipeline when mandatory fields or the root dependency graph are absent
  • Diff SBOMs after tool upgrades and investigate large component-count changes
  • Attach exceptions, known blind spots and reviewer approval to the conformity evidence

A small example: valid file, wrong assurance

Consider a JavaScript service with one production dependency, a workspace package and a development tool that bundles code into the released asset. Tool A reads only the root lockfile and reports the production package. Tool B follows the workspace and reports both runtime packages. Tool C also reports the development tool because its output is embedded during the build. All three files can be valid CycloneDX. Only the organisation's product-boundary decision tells a reviewer which inventory is acceptable.

The control cannot be “SBOM generated”. It must state what was scanned, what should have been present, what was excluded and how the result was tested.

Key facts

Sources

  1. PrimaryMind the Gap: How SBOM Specification Ambiguities Lead to Divergent Software Bills of MaterialsarXivaccessed 2026-09-20
  2. PrimaryRegulation (EU) 2024/2847, Cyber Resilience ActEUR-Lexaccessed 2026-09-20

Share this briefing

Know someone who owns this problem? Send it to them.

Related briefings

The briefing, in your inbox

Practitioner analysis of cyber and AI security news. No vendor noise.

One email per briefing. Unsubscribe any time.