---
title: SBOM attestations
keywords: build, attestations, sbom, spdx, metadata, packages
description: |
  SBOM attestations describe what software artifacts an image contains and the artifacts used to create the image.
aliases:
  - /build/attestations/sbom/
---

SBOM attestations help ensure [software supply chain transparency](/guides/docker-scout/s3c.md) by verifying the software artifacts an image contains and the artifacts used to create the image. Metadata included in an [SBOM](/guides/docker-scout/sbom.md) for describing software artifacts may include:

- Name of the artifact
- Version
- License type
- Authors
- Unique package identifier

Indexing the contents of an image during the build has benefits over scanning a final image. When scanning happens as part of the build, you can detect software you used to build the image, which may not show up in the final image.

Docker supports SBOM generation and attestation through an SLSA-compliant build process using BuildKit and attestations. The SBOMs generated by [BuildKit](/manuals/build/buildkit/_index.md) follow the SPDX standard and attach to the final image as a JSON-encoded SPDX document, using the format defined by the [in-toto SPDX predicate](https://github.com/in-toto/attestation/blob/main/spec/predicates/spdx.md). On this page, you’ll learn how to create, manage, and verify SBOM attestations using Docker tooling.

## Create SBOM attestations

To create an SBOM attestation, pass the `--attest type=sbom` option to the
`docker buildx build` command:

```console
$ docker buildx build --tag <namespace>/<image>:<version> \
    --attest type=sbom --push .
```

Alternatively, you can use the shorthand `--sbom=true` option instead of `--attest type=sbom`.

For an example on how to add SBOM attestations with GitHub Actions, see
[Add attestations with GitHub Actions](/manuals/build/ci/github-actions/attestations.md).

## Verify SBOM attestations

Always validate the generated SBOM for your image before you push your image to a registry.

To validate, you can build the image using the `local` exporter.
Building with the `local` exporter saves the build result to your local filesystem instead of creating an image.
Attestations are written to a JSON file in the root directory of your export.

```console
$ docker buildx build \
  --sbom=true \
  --output type=local,dest=out .
```

The SBOM file appears in the root directory of the output, named `sbom.spdx.json`:

```console
$ ls -1 ./out | grep sbom
sbom.spdx.json
```

## Arguments

By default, BuildKit only scans the final stage of an image. The resulting SBOM
doesn't include build-time dependencies installed in earlier stages, or that
exist in the build context. This may cause you to overlook vulnerabilities in
those dependencies, which could impact the security of your final build
artifacts.

For instance, you might use [multi-stage builds](/manuals/build/building/multi-stage.md),
with a `FROM scratch` stanza for your final stage to achieve a smaller image size.

```dockerfile
FROM alpine AS build
# build the software ...

FROM scratch
COPY --from=build /path/to/bin /bin
ENTRYPOINT [ "/bin" ]
```

Scanning the resulting image built using this Dockerfile example would not
reveal build-time dependencies used in the `build` stage.

To include build-time dependencies from your Dockerfile, you can set the build
arguments `BUILDKIT_SBOM_SCAN_CONTEXT` and `BUILDKIT_SBOM_SCAN_STAGE`. This
expands the scanning scope to include the build context and additional stages.

You can set the arguments as global arguments (after declaring the Dockerfile
syntax directive, before the first `FROM` command) or individually in each
stage. If set globally, the value propagates to each stage in the Dockerfile.

The `BUILDKIT_SBOM_SCAN_CONTEXT` and `BUILDKIT_SBOM_SCAN_STAGE` build arguments
are special values. You can't perform variable substitution using these
arguments, and you can't set them using environment variables from within the
Dockerfile. The only way to set these values is using explicit `ARG` command in
the Dockerfile.

### Scan build context

To scan the build context, set the `BUILDKIT_SBOM_SCAN_CONTEXT` to `true`.

```dockerfile
# syntax=docker/dockerfile:1
ARG BUILDKIT_SBOM_SCAN_CONTEXT=true
FROM alpine AS build
# ...
```

You can use the `--build-arg` CLI option to override the value specified in the
Dockerfile.

```console
$ docker buildx build --tag <image>:<version> \
    --attest type=sbom \
    --build-arg BUILDKIT_SBOM_SCAN_CONTEXT=false .
```

Note that passing the option as a CLI argument only, without having declared it
using `ARG` in the Dockerfile, will have no effect. You must specify the `ARG`
in the Dockerfile, whereby you can override the context scanning behavior using
`--build-arg`.

### Scan stages

To scan more than just the final stage, set the `BUILDKIT_SBOM_SCAN_STAGE`
argument to true, either globally or in the specific stages that you want to
scan. The following table demonstrates the different possible settings for this
argument.

| Value                               | Description                                            |
| ----------------------------------- | ------------------------------------------------------ |
| `BUILDKIT_SBOM_SCAN_STAGE=true`     | Enables scanning for the current stage                 |
| `BUILDKIT_SBOM_SCAN_STAGE=false`    | Disables scanning for the current stage                |
| `BUILDKIT_SBOM_SCAN_STAGE=base,bin` | Enables scanning for the stages named `base` and `bin` |

Only stages that are built will be scanned. Stages that aren't dependencies of
the target stage won't be built, or scanned.

The following Dockerfile example uses multi-stage builds to build a static website with
[Hugo](https://gohugo.io/).

```dockerfile
# syntax=docker/dockerfile:1
FROM alpine as hugo
ARG BUILDKIT_SBOM_SCAN_STAGE=true
WORKDIR /src
COPY <<config.yml ./
title: My Hugo website
config.yml
RUN apk add --upgrade hugo && hugo

FROM scratch
COPY --from=hugo /src/public /
```

Setting `ARG BUILDKIT_SBOM_SCAN_STAGE=true` in the `hugo` stage ensures that the final SBOM
includes the information that Alpine Linux and Hugo were used to create the website.

Building this image with the `local` exporter creates two JSON files:

```console
$ docker buildx build \
  --sbom=true \
  --output type=local,dest=out .
$ ls -1 out | grep sbom
sbom-hugo.spdx.json
sbom.spdx.json
```

## Inspecting SBOMs

To explore created SBOMs exported through the `image` exporter, you can use
[`imagetools inspect`](/reference/cli/docker/buildx/imagetools/inspect/).

Using the `--format` option, you can specify a template for the output. All
SBOM-related data is available under the `.SBOM` attribute. For example, to get
the raw contents of an SBOM in SPDX format:

```console
$ docker buildx imagetools inspect <namespace>/<image>:<version> \
    --format "{{ json .SBOM.SPDX }}"
{
  "SPDXID": "SPDXRef-DOCUMENT",
  ...
}
```

> [!TIP]
>
> If the image is multi-platform, you can check the SBOM for a platform-specific index using `--format '{{ json (index .SBOM "linux/amd64").SPDX }}'`.

You can also construct more complex expressions using the full functionality
of Go templates. For example, you can list all the installed packages and their
version identifiers:

```console
$ docker buildx imagetools inspect <namespace>/<image>:<version> \
    --format "{{ range .SBOM.SPDX.packages }}{{ .name }}@{{ .versionInfo }}{{ println }}{{ end }}"
adduser@3.118ubuntu2
apt@2.0.9
base-files@11ubuntu5.6
base-passwd@3.5.47
...
```

## SBOM generator

BuildKit generates the SBOM using a scanner plugin. By default, it uses is the
[BuildKit Syft scanner](https://github.com/docker/buildkit-syft-scanner)
plugin. This plugin is built on top of
[Anchore's Syft](https://github.com/anchore/syft),
an open source tool for generating an SBOM.

You can select a different plugin to use with the `generator` option, specifying
an image that implements the
[BuildKit SBOM scanner protocol](https://github.com/moby/buildkit/blob/master/docs/attestations/sbom-protocol.md).

```console
$ docker buildx build --attest type=sbom,generator=<image> .
```

> [!TIP]
>
> The Docker Scout SBOM generator is available. See
> [Docker Scout SBOMs](/manuals/scout/how-tos/view-create-sboms.md).

## SBOM attestation example

The following JSON example shows what an SBOM attestation might look like.

```json
{
  "_type": "https://in-toto.io/Statement/v0.1",
  "predicateType": "https://spdx.dev/Document",
  "subject": [
    {
      "name": "pkg:docker/<registry>/<image>@<tag/digest>?platform=<platform>",
      "digest": {
        "sha256": "e8275b2b76280af67e26f068e5d585eb905f8dfd2f1918b3229db98133cb4862"
      }
    }
  ],
  "predicate": {
    "SPDXID": "SPDXRef-DOCUMENT",
    "creationInfo": {
      "created": "2022-12-16T15:27:25.517047753Z",
      "creators": ["Organization: Anchore, Inc", "Tool: syft-v0.60.3"],
      "licenseListVersion": "3.18"
    },
    "dataLicense": "CC0-1.0",
    "documentNamespace": "https://anchore.com/syft/dir/run/src/core/sbom-cba61a72-fa95-4b60-b63f-03169eac25ca",
    "name": "/run/src/core/sbom",
    "packages": [
      {
        "SPDXID": "SPDXRef-b074348b8f56ea64",
        "downloadLocation": "NOASSERTION",
        "externalRefs": [
          {
            "referenceCategory": "SECURITY",
            "referenceLocator": "cpe:2.3:a:org:repo:\\(devel\\):*:*:*:*:*:*:*",
            "referenceType": "cpe23Type"
          },
          {
            "referenceCategory": "PACKAGE_MANAGER",
            "referenceLocator": "pkg:golang/github.com/org/repo@(devel)",
            "referenceType": "purl"
          }
        ],
        "filesAnalyzed": false,
        "licenseConcluded": "NONE",
        "licenseDeclared": "NONE",
        "name": "github.com/org/repo",
        "sourceInfo": "acquired package info from go module information: bin/server",
        "versionInfo": "(devel)"
      },
      {
        "SPDXID": "SPDXRef-1b96f57f8fed62d8",
        "checksums": [
          {
            "algorithm": "SHA256",
            "checksumValue": "0c13f1f3c1636491f716c2027c301f21f9dbed7c4a2185461ba94e3e58443408"
          }
        ],
        "downloadLocation": "NOASSERTION",
        "externalRefs": [
          {
            "referenceCategory": "SECURITY",
            "referenceLocator": "cpe:2.3:a:go-chi:chi\\/v5:v5.0.0:*:*:*:*:*:*:*",
            "referenceType": "cpe23Type"
          },
          {
            "referenceCategory": "SECURITY",
            "referenceLocator": "cpe:2.3:a:go_chi:chi\\/v5:v5.0.0:*:*:*:*:*:*:*",
            "referenceType": "cpe23Type"
          },
          {
            "referenceCategory": "SECURITY",
            "referenceLocator": "cpe:2.3:a:go:chi\\/v5:v5.0.0:*:*:*:*:*:*:*",
            "referenceType": "cpe23Type"
          },
          {
            "referenceCategory": "PACKAGE_MANAGER",
            "referenceLocator": "pkg:golang/github.com/go-chi/chi/v5@v5.0.0",
            "referenceType": "purl"
          }
        ],
        "filesAnalyzed": false,
        "licenseConcluded": "NONE",
        "licenseDeclared": "NONE",
        "name": "github.com/go-chi/chi/v5",
        "sourceInfo": "acquired package info from go module information: bin/server",
        "versionInfo": "v5.0.0"
      }
    ],
    "relationships": [
      {
        "relatedSpdxElement": "SPDXRef-1b96f57f8fed62d8",
        "relationshipType": "CONTAINS",
        "spdxElementId": "SPDXRef-043f7360d3c66bc31ba45388f16423aa58693289126421b71d884145f8837fe1"
      },
      {
        "relatedSpdxElement": "SPDXRef-b074348b8f56ea64",
        "relationshipType": "CONTAINS",
        "spdxElementId": "SPDXRef-043f7360d3c66bc31ba45388f16423aa58693289126421b71d884145f8837fe1"
      }
    ],
    "spdxVersion": "SPDX-2.2"
  }
}
```
