---
title: SLSA provenance
---

BuildKit supports automatic creation of provenance attestations for the build
process. Provenance attestations record information describing how a build was
created, and is important for tracking the security of your software artifacts.

Provenance attestations created by BuildKit include details such as:

- Build parameters and environment.
- Build timestamps.
- Version control metadata for your build sources.
- Build dependencies with their immutable checksums. For example, base images or external URLs used by the build.
- Descriptions of all build steps, with their source and layer mappings.

Provenance generated by BuildKit is wrapped inside [in-toto attestations](https://github.com/in-toto/attestation)
in the SLSA Provenance format (supports both [v0.2](https://slsa.dev/spec/v0.2/provenance) and [v1](https://slsa.dev/spec/v1.1/provenance)).

For more information about how the attestation fields get generated, see [SLSA definitions](./slsa-definitions.md).

## Build with provenance attestations

To build an image with provenance attestations using `buildctl`, use the `attest:provenance` option:

```bash
buildctl build \
    --frontend=dockerfile.v0 \
    --local context=. \
    --local dockerfile=. \
    --opt attest:provenance=
```

You can also customize the attestations using parameters:

```bash
buildctl build \
    --frontend=dockerfile.v0 \
    --local context=. \
    --local dockerfile=. \
    --opt attest:provenance=mode=min,inline-only=true
```

All BuildKit exporters support attaching attestations to build results.
When the final output format is a container image (`image` or `oci` exporter), provenance is attached
to the image using the format described in the [attestation storage specification](./attestation-storage.md).
When creating a multi-platform image, each platform version of the image gets its own provenance.

If you use the `local` or `tar` exporter, the provenance will be written to a file named `provenance.json`
and exported with your build result, in the root directory.

## Parameters

| Parameter      | Type           | Default           | Description                                                                                       |
|----------------|----------------|-------------------|---------------------------------------------------------------------------------------------------|
| `mode`         | `min`,`max`    | `max`             | Configures the amount of provenance to be generated. See [mode](#mode)                            |
| `builder-id`   | String         |                   | Explicitly set SLSA Builder ID field. See [builder-id](#builder-id)                               |
| `filename`     | String         | `provenance.json` | Set filename for provenance attestation when exported with `local` or `tar` exporter              |
| `reproducible` | `true`,`false` | `false`           | Explicitly marked as reproducible. See [reproducible](#reproducible)                              |
| `inline-only`  | `true`,`false` | `false`           | Only embed provenance into exporters that support inline content. See [inline-only](#inline-only) |
| `version`      | String         | `v0.2`            | SLSA provenance version to use (`v0.2` or `v1`)                                                   |

### `mode`

Provenance can be generated in one of two modes: `min` or `max`. By default,
when provenance is enabled, the `mode` parameter will be set to `max`.

In `min` mode, BuildKit generates only the bare minimum amount of provenance,
including:

- Build timestamps
- The frontend used
- The build materials

However, the values of build arguments, the identities of secrets, and rich
layer metadata will not be included. `mode=min` should be safe to set on all
builds, as it does not leak information from any part of the build environment.

In `max` mode, BuildKit generates all of the above, as well as:

- The source Dockerfile, and rich layer metadata with sourcemaps to connect the
  source with the build result
- The values of passed build arguments
- Metadata about secrets and ssh mounts

Wherever possible, you should prefer `mode=max` as it contains significantly
more detailed information for analysis. However, on some builds it may not be
appropriate, as it includes the values of various build arguments and metadata
about secrets - these builds should be refactored to prefer passing hidden
values through secrets wherever possible to prevent unnecessary information
leakage.

### `builder-id`

Depends on the SLSA `version` used:

| SLSA version | Field                                                                       |
|--------------|-----------------------------------------------------------------------------|
| `v1`         | [`runDetails.builder.id`](https://slsa.dev/spec/v1.1/provenance#builder.id) |
| `v0.2`       | [`builder.id`](https://slsa.dev/spec/v0.2/provenance#builder.id)            |

### `reproducible`

Depends on the SLSA `version` used:

| SLSA version | Field                                                                                  |
|--------------|----------------------------------------------------------------------------------------|
| `v1`         | [`runDetails.metadata.buildkit_reproducible`                                           |
| `v0.2`       | [`metadata.reproducible`](https://slsa.dev/spec/v0.2/provenance#metadata.reproducible) |

### `inline-only`

By default, provenance is by included in all exporters that support
attestations. The `inline-only` parameter allows configuring this behavior, to
only include the provenance results in exporters that support inline content,
specifically only exporters that produce container images.

Since other exporters produce attestations into separate files, in their
filesystems, you may not want to include the provenance in these cases.

## Output

To inspect the provenance that was generated and attached to a container image,
you can use the `docker buildx imagetools` command to inspect the image in a
registry. Inspecting the attestation displays the format described in the
[attestation storage specification](./attestation-storage.md).

For example, inspecting a simple Docker image based on `alpine:latest`:

```dockerfile
FROM alpine:latest
```

Results in a provenance attestation similar to the following, for a `mode=min`
build:

```json
{
  "_type": "https://in-toto.io/Statement/v0.1",
  "predicateType": "https://slsa.dev/provenance/v0.2",
  "subject": [
    {
      "name": "pkg:docker/<registry>/<image>@<tag/digest>?platform=<platform>",
      "digest": {
        "sha256": "e8275b2b76280af67e26f068e5d585eb905f8dfd2f1918b3229db98133cb4862"
      }
    }
  ],
  "predicate": {
    "builder": {
      "id": ""
    },
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/alpine@latest?platform=linux%2Famd64",
        "digest": {
          "sha256": "8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "Dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {},
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dockerfile"
          }
        ]
      },
      "environment": {
        "platform": "linux/amd64"
      }
    },
    "metadata": {
      "buildInvocationID": "yirbp1aosi1vqjmi3z6bc75nb",
      "buildStartedOn": "2022-12-08T11:48:59.466513707Z",
      "buildFinishedOn": "2022-12-08T11:49:01.256820297Z",
      "reproducible": false,
      "completeness": {
        "parameters": true,
        "environment": true,
        "materials": false
      },
      "https://mobyproject.org/buildkit@v1#metadata": {}
    }
  }
}
```

For a similar build, but with `mode=max`:

```json
{
  "_type": "https://in-toto.io/Statement/v0.1",
  "predicateType": "https://slsa.dev/provenance/v0.2",
  "subject": [
    {
      "name": "pkg:docker/<registry>/<image>@<tag/digest>?platform=<platform>",
      "digest": {
        "sha256": "e8275b2b76280af67e26f068e5d585eb905f8dfd2f1918b3229db98133cb4862"
      }
    }
  ],
  "predicate": {
    "builder": {
      "id": ""
    },
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/alpine@latest?platform=linux%2Famd64",
        "digest": {
          "sha256": "8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "Dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {},
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dockerfile"
          }
        ]
      },
      "environment": {
        "platform": "linux/amd64"
      }
    },
    "buildConfig": {
      "llbDefinition": [
        {
          "id": "step0",
          "op": {
            "Op": {
              "source": {
                "identifier": "docker-image://docker.io/library/alpine:latest@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4"
              }
            },
            "platform": {
              "Architecture": "amd64",
              "OS": "linux"
            },
            "constraints": {}
          }
        },
        {
          "id": "step1",
          "op": {
            "Op": null
          },
          "inputs": ["step0:0"]
        }
      ]
    },
    "metadata": {
      "buildInvocationID": "46ue2x93k3xj5l463dektwldw",
      "buildStartedOn": "2022-12-08T11:50:54.953375437Z",
      "buildFinishedOn": "2022-12-08T11:50:55.447841328Z",
      "reproducible": false,
      "completeness": {
        "parameters": true,
        "environment": true,
        "materials": false
      },
      "https://mobyproject.org/buildkit@v1#metadata": {
        "source": {
          "locations": {
            "step0": {
              "locations": [
                {
                  "ranges": [
                    {
                      "start": {
                        "line": 1
                      },
                      "end": {
                        "line": 1
                      }
                    }
                  ]
                }
              ]
            }
          },
          "infos": [
            {
              "filename": "Dockerfile",
              "data": "RlJPTSBhbHBpbmU6bGF0ZXN0Cg==",
              "llbDefinition": [
                {
                  "id": "step0",
                  "op": {
                    "Op": {
                      "source": {
                        "identifier": "local://dockerfile",
                        "attrs": {
                          "local.differ": "none",
                          "local.followpaths": "[\"Dockerfile\",\"Dockerfile.dockerignore\",\"dockerfile\"]",
                          "local.session": "q2jnwdkas0i0iu4knchd92jaz",
                          "local.sharedkeyhint": "dockerfile"
                        }
                      }
                    },
                    "constraints": {}
                  }
                },
                {
                  "id": "step1",
                  "op": {
                    "Op": null
                  },
                  "inputs": ["step0:0"]
                }
              ]
            }
          ]
        },
        "layers": {
          "step0:0": [
            [
              {
                "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
                "digest": "sha256:c158987b05517b6f2c5913f3acef1f2182a32345a304fe357e3ace5fadcad715",
                "size": 3370706
              }
            ]
          ]
        }
      }
    }
  }
}
```
