Provetry opens in November 2026. The free CRA check, the tools and the guides are available now.

SBOM for Docker and container images under the CRA

7 min read

On this page
  1. When the image is part of the product
  2. Two SBOMs, and why you want both
  3. Generate the image SBOM
  4. Base images and what they bring
  5. From SBOM to vulnerabilities
  6. How Provetry helps
  7. Sources

The Cyber Resilience Act asks every manufacturer to keep a software bill of materials “in a commonly used and machine-readable format covering at the very least the top-level dependencies” of the product (Annex I, Part II, point 1). When you deliver your software as a container image, the image is what the customer runs. Everything inside it is part of what you place on the market: your code and its libraries, but also the base image’s operating system packages, the language runtime, and any binary copied in along the way.

For the regulation itself, see SBOM for the Cyber Resilience Act.

When the image is part of the product

  • You ship the image to customers, who run it on their own servers or clusters (self-hosted software, an on-premises edition, an appliance, a Helm chart that pulls your images). The image is the product, or part of it, and its SBOM must cover all of it.
  • You run the image yourself to provide a service. A pure SaaS is generally outside the CRA, unless it is the remote data processing of a product (see The CRA and SaaS). The image’s SBOM is still good practice, but it is not a CRA document.
  • A device runs containers. On a gateway or an industrial PC, the images are part of the firmware, and belong in the device’s SBOM.

Two SBOMs, and why you want both

A source SBOM, built from your lock files (see the guides for npm, Python, Java, Rust, Go and .NET), knows your direct dependencies and the dependency graph. It does not know the base image.

An image SBOM, built by scanning the finished image, sees what is actually installed: Debian, Alpine or Red Hat packages, the Python or Java runtime, language packages from their installed metadata, Go binaries from their build information. It does not know which of those your code asked for, and it can miss what leaves no metadata behind, such as a C library compiled from source or a binary downloaded with curl in the Dockerfile.

Keep both for each release. The image SBOM answers “is this vulnerable OpenSSL in what we ship?”; the source SBOM answers “is it ours, and why is it there?”.

Generate the image SBOM

Syft, from Anchore, scans an image from a registry, the local Docker daemon or an archive:

syft registry.example.com/acme/gateway:2.4.0 -o cyclonedx-json=sbom.cdx.json

Trivy, from Aqua Security, does the same:

trivy image --format cyclonedx --output sbom.cdx.json registry.example.com/acme/gateway:2.4.0

Or let BuildKit write the SBOM during the build and attach it to the image as an attestation (SPDX, generated by a Syft-based scanner):

docker buildx build --sbom=true -t registry.example.com/acme/gateway:2.4.0 --push .

Attestations need a builder that supports them (the docker-container driver, or Docker’s containerd image store). They travel with the image in the registry, and docker buildx imagetools inspect reads them back. To get a plain SPDX file, which is what other tools expect:

docker buildx imagetools inspect registry.example.com/acme/gateway:2.4.0 --format '{{ json .SBOM.SPDX }}' > sbom.spdx.json

Whichever tool you choose, describe the exact image you release, by digest, not a tag that will later point to another image.

Base images and what they bring

  • Every package in the base image is yours to handle. A Debian base adds around a hundred packages, most of which your application never uses. Each can carry a vulnerability, and many scanners will report it against your product.
  • Smaller is easier. Distroless, Chainguard, Alpine or scratch images for static binaries carry far fewer components, and so fewer vulnerabilities to assess and fewer questions from customers.
  • Rebuild regularly. A base image tag such as debian:12-slim receives fixes; your image does not, until you rebuild it. Rebuild on a schedule, and when an exploited vulnerability touches the base image, not only when your code changes.
  • Pin the base image by digest in the Dockerfile, so that each SBOM matches what was built.
  • Multi-stage builds help. Compilers and build tools stay in the build stage and do not reach the final image, or its SBOM.

From SBOM to vulnerabilities

Grype reads Syft’s SBOMs, and trivy sbom sbom.cdx.json checks a stored SBOM against today’s advisories without pulling the image again. Expect many findings on OS packages that your application never calls. Look first at the vulnerabilities exploited in the wild, which can start the reporting clock, and record in a VEX statement why the others do not affect the product. Distributions also publish their own assessments, such as Debian’s and Red Hat’s “not affected” or “will not fix” decisions, which are worth checking before you write your own.

How Provetry helps

Upload the image’s SBOM from Syft, Trivy or BuildKit (CycloneDX or SPDX JSON, SPDX 3 included; for BuildKit, the file extracted as above), or let Provetry’s CI step read the image itself (its image input takes an image name or a docker save archive; provetry sbom gateway.tar does the same locally): Debian, Ubuntu and Alpine packages with their release, Wolfi and Chainguard packages, opkg packages, and the Python and Node.js packages installed in the image. RPM-based images are not read yet: the SBOM says so. Syft and Trivy list their RPM packages (the step’s image-tool: syft uses Syft), but Provetry does not look RPM packages up yet, nor opkg packages and releases no public advisory database covers (Debian testing, Alpine edge); a derivative distribution such as Raspberry Pi OS is looked up only approximately, as the release it follows. The release shows which components are not watched. A release holds one SBOM: when it describes the image, it covers the language packages installed in it too, but reachability analysis is skipped, so keep the SBOM of your lock files with your build artifacts. Provetry keeps each release’s SBOM, watches every component it can look up, OS packages included, for new and exploited vulnerabilities, every day on paid plans and every week on Free, and, on the Pro and Consultant plans, once you set the end of your support period in the product’s profile, flags components whose support ends before yours, for those endoflife.date knows (mostly runtimes, frameworks and databases). Its reachability analysis reads source code, so it does not cover the other binaries in an image: for those, your own assessment is recorded as a VEX statement.

Sources