Generating SBOMs
The principle
The SBOM is produced as close to the artefact as possible, in the pipeline that builds it, never by hand afterwards. An SBOM written by a human is wrong the day it is written and obsolete the next.
The five methods
| Method | What it sees | Blind spot |
|---|---|---|
| From dependency manifests | Declared and resolved dependencies | Whatever is not declared: vendored code, static linking |
| From the container image | Base image system packages and the application | Anything compiled into a binary |
| From the compiled binary | Statically linked libraries | Accuracy varies with the metadata the compiler leaves |
| From the file system or firmware | The real content of an embedded image | Expensive, specialised tooling |
| From execution | What is actually loaded in memory | Only sees exercised paths |
These methods are not mutually exclusive: they combine. A mature pipeline produces a build SBOM from manifests and an analysed SBOM from the artefact, then compares the two.
The tool families
Detailed profiles are in Generators. In summary:
| Family | Role | Representatives |
|---|---|---|
| Generic generators | Produce the inventory, multi-ecosystem | Syft, cdxgen |
| All-in-one scanners | Generate and detect vulnerabilities in one pass | Trivy |
| Detection engines | Consume an SBOM and correlate it | Grype, osv-scanner |
| Licence-oriented tools | Detect licences by analysing file content | ScanCode, OSS Review Toolkit |
| Native build-chain plugins | Produce the inventory from the real resolution graph | CycloneDX Maven/Gradle, npm sbom, .NET, Rust, Go equivalents |
Choice matrix by context
| Context | Recommendation | Why |
|---|---|---|
| Java, .NET, Node, Python, Ruby applications | Native build-chain plugin, complemented by a generic generator on the artefact | The plugin sees the real resolution graph, with version arbitration |
| Go or Rust applications | Generic generator on the binary | Build metadata is present there |
| C / C++ applications | Generator on the binary and on the build system | Static linking makes manifests insufficient |
| Container image | Generator on the full image | Captures the base image |
| Embedded firmware | Specialised tooling, and an SBOM requirement on the platform supplier | Few general tools cover this case |
| Multi-artefact monorepo | One SBOM per publishable artefact, not one for the repository | An SBOM describes a shipped artefact |
The floating-toolchain trap
Two different tools produce two different SBOMs for the same artefact: detection scope, granularity, identifier normalisation and handling of test dependencies all vary. That is normal, and it is only a problem if the toolchain changes without your knowing.
Rule. Pin the toolchain per product family, document the choice, version the configuration, and treat any tool change or major version bump as an event: recompute a baseline, compare, write an explanatory note.
Without that discipline, comparability over time is lost and differences between two versions become uninterpretable — which drains the arrangement of its value for the technical documentation.
What must come out of the pipeline
For every publishable artefact:
- a build SBOM in the pivot format, at a fixed version;
- an analysed SBOM as a cross-check;
- a quality score, with the build failing below the threshold;
- a signature and a provenance attestation;
- publication to the steering platform;
- archiving with indexing by hash.
The detail is in CI/CD integration.
What to document
One sheet per product family: tools used and versions, exact commands, output format and version, scope covered, deliberate exclusions and their reasons, quality thresholds, owner. That sheet is part of the technical documentation, because it explains how the SBOM was produced — information Annex VII expects under the process heading.