# SLSA definitions and more

# SLSA definitions

# SLSA definitions

   Table of contents

---

BuildKit supports the [creation of SLSA Provenance](https://docs.docker.com/build/metadata/attestations/slsa-provenance/) for
builds that it runs.

The provenance format generated by BuildKit is defined by the
SLSA Provenance format (supports both [v0.2](https://slsa.dev/spec/v0.2/provenance)
and [v1](https://slsa.dev/spec/v1.1/provenance)).

This page describes how BuildKit populate each field, and whether the field gets
included when you generate attestations `mode=min` and `mode=max`.

## SLSA v1

### buildDefinition.buildType

- Ref: [https://slsa.dev/spec/v1.1/provenance#buildType](https://slsa.dev/spec/v1.1/provenance#buildType)
- Included with `mode=min` and `mode=max`.

The `buildDefinition.buildType` field is set to `https://github.com/moby/buildkit/blob/master/docs/attestations/slsa-definitions.md`
and can be used to determine the structure of the provenance content.

```json
"buildDefinition": {
      "buildType": "https://github.com/moby/buildkit/blob/master/docs/attestations/slsa-definitions.md",
      ...
    }
```

### buildDefinition.externalParameters.configSource

- Ref: [https://slsa.dev/spec/v1.1/provenance#externalParameters](https://slsa.dev/spec/v1.1/provenance#externalParameters)
- Included with `mode=min` and `mode=max`.

Describes the config that initialized the build.

```json
"buildDefinition": {
      "externalParameters": {
        "configSource": {
          "uri": "https://github.com/moby/buildkit.git#refs/tags/v0.11.0",
          "digest": {
            "sha1": "4b220de5058abfd01ff619c9d2ff6b09a049bea0"
          },
          "path": "Dockerfile"
        },
        ...
      },
    }
```

For builds initialized from a remote context, like a Git or HTTP URL, this
object defines the context URL and its immutable digest in the `uri` and
`digest` fields. For builds using a local frontend, such as a Dockerfile, the
`path` field defines the path for the frontend file that initialized the build
(`filename` frontend option).

### buildDefinition.externalParameters.request

- Ref: [https://slsa.dev/spec/v1.1/provenance#externalParameters](https://slsa.dev/spec/v1.1/provenance#externalParameters)
- Partially included with `mode=min`.

Describes build inputs passed to the build.

```json
"buildDefinition": {
      "externalParameters": {
        "request": {
          "frontend": "gateway.v0",
          "args": {
            "build-arg:BUILDKIT_CONTEXT_KEEP_GIT_DIR": "1",
            "label:FOO": "bar",
            "source": "docker/dockerfile-upstream:master",
            "target": "release"
          },
          "secrets": [
            {
              "id": "GIT_AUTH_HEADER",
              "optional": true
            },
            ...
          ],
          "ssh": [],
          "locals": []
        },
        ...
      },
    }
```

The following fields are included with both `mode=min` and `mode=max`:

- `locals` lists any local sources used in the build, including the build
  context and frontend file.
- `frontend` defines type of BuildKit frontend used for the build. Currently,
  this can be `dockerfile.v0` or `gateway.v0`.
- `args` defines the build arguments passed to the BuildKit frontend.
  The keys inside the `args` object reflect the options as BuildKit receives
  them. For example, `build-arg` and `label` prefixes are used for build
  arguments and labels, and `target` key defines the target stage that was
  built. The `source` key defines the source image for the Gateway frontend, if
  used.

The following fields are only included with `mode=max`:

- `secrets` defines secrets used during the build. Note that actual secret
  values are not included.
- `ssh` defines the ssh forwards used during the build.

### buildDefinition.internalParameters.buildConfig

- Ref: [https://slsa.dev/spec/v1.1/provenance#internalParameters](https://slsa.dev/spec/v1.1/provenance#internalParameters)
- Only included with `mode=max`.

Defines the build steps performed during the build.

BuildKit internally uses LLB definition to execute the build steps. The LLB
definition of the build steps is defined in the
`buildDefinition.internalParameters.buildConfig.llbDefinition` field.

Each LLB step is the JSON definition of the
[LLB ProtoBuf API](https://github.com/moby/buildkit/blob/v0.10.0/solver/pb/ops.proto).
The dependencies for a vertex in the LLB graph can be found in the `inputs`
field for every step.

```json
"buildDefinition": {
      "internalParameters": {
        "buildConfig": {
          "llbDefinition": [
            {
              "id": "step0",
              "op": {
                "Op": {
                  "exec": {
                    "meta": {
                      "args": [
                        "/bin/sh",
                        "-c",
                        "go build ."
                      ],
                      "env": [
                        "PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                        "GOPATH=/go",
                        "GOFLAGS=-mod=vendor",
                      ],
                      "cwd": "/src",
                    },
                    "mounts": [...]
                  }
                },
                "platform": {...},
              },
              "inputs": [
                "step8:0",
                "step2:0",
              ]
            },
            ...
          ]
        },
      }
    }
```

### buildDefinition.internalParameters.builderPlatform

- Ref: [https://slsa.dev/spec/v1.1/provenance#internalParameters](https://slsa.dev/spec/v1.1/provenance#internalParameters)
- Included with `mode=min` and `mode=max`.

```json
"buildDefinition": {
      "internalParameters": {
        "builderPlatform": "linux/amd64"
        ...
      },
    }
```

BuildKit sets the `builderPlatform` of the build machine. Note that this is not
necessarily the platform of the build result that can be determined from the
`in-toto` subject field.

### buildDefinition.resolvedDependencies

- Ref: [https://slsa.dev/spec/v1.1/provenance#resolvedDependencies](https://slsa.dev/spec/v1.1/provenance#resolvedDependencies)
- Included with `mode=min` and `mode=max`.

Defines all the external artifacts that were part of the build. The value
depends on the type of artifact:

- The URL of Git repositories containing source code for the image
- HTTP URLs if you are building from a remote tarball, or that was included
  using an `ADD` command in Dockerfile
- Any Docker images used during the build

The URLs to the Docker images will be in
[Package URL](https://github.com/package-url/purl-spec) format.

All the build materials will include the immutable checksum of the artifact.
When building from a mutable tag, you can use the digest information to
determine if the artifact has been updated compared to when the build ran.

```json
"buildDefinition": {
      "resolvedDependencies": [
        {
          "uri": "pkg:docker/alpine@3.17?platform=linux%2Famd64",
          "digest": {
            "sha256": "8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4"
          }
        },
        {
          "uri": "https://github.com/moby/buildkit.git#refs/tags/v0.11.0",
          "digest": {
            "sha1": "4b220de5058abfd01ff619c9d2ff6b09a049bea0"
          }
        },
        ...
      ],
      ...
    }
```

### runDetails.builder.id

- Ref: [https://slsa.dev/spec/v1.1/provenance#builder.id](https://slsa.dev/spec/v1.1/provenance#builder.id)
- Included with `mode=min` and `mode=max`.

The field is set to the URL of the build, if available.

```json
"runDetails": {
      "builder": {
        "id": "https://github.com/docker/buildx/actions/runs/3709599520"
        ...
      },
      ...
    }
```

> Note
>
> This value can be set using the `builder-id` attestation parameter.

### runDetails.metadata.invocationID

- Ref: [https://slsa.dev/spec/v1.1/provenance#invocationId](https://slsa.dev/spec/v1.1/provenance#invocationId)
- Included with `mode=min` and `mode=max`.

Unique identifier for the build invocation. When building a multi-platform image
with a single build request, this value will be the shared by all the platform
versions of the image.

```json
"runDetails": {
      "metadata": {
        "invocationID": "rpv7a389uzil5lqmrgwhijwjz",
        ...
      },
      ...
    }
```

### runDetails.metadata.startedOn

- Ref: [https://slsa.dev/spec/v1.1/provenance#startedOn](https://slsa.dev/spec/v1.1/provenance#startedOn)
- Included with `mode=min` and `mode=max`.

Timestamp when the build started.

```json
"runDetails": {
      "metadata": {
        "startedOn": "2021-11-17T15:00:00Z",
        ...
      },
      ...
    }
```

### runDetails.metadata.finishedOn

- Ref: [https://slsa.dev/spec/v1.1/provenance#finishedOn](https://slsa.dev/spec/v1.1/provenance#finishedOn)
- Included with `mode=min` and `mode=max`.

Timestamp when the build finished.

```json
"runDetails": {
      "metadata": {
        "finishedOn": "2021-11-17T15:01:00Z",
        ...
      },
    }
```

### runDetails.metadata.buildkit_metadata

- Ref: [https://slsa.dev/spec/v1.1/provenance#extension-fields](https://slsa.dev/spec/v1.1/provenance#extension-fields)
- Partially included with `mode=min`.

This extension field defines BuildKit-specific additional metadata that is not
part of the SLSA provenance spec.

```json
"runDetails": {
      "metadata": {
        "buildkit_metadata": {
          "source": {...},
          "layers": {...},
          "vcs": {...},
        },
        ...
      },
    }
```

#### source

Only included with `mode=max`.

Defines a source mapping of LLB build steps, defined in the
`buildDefinition.internalParameters.buildConfig.llbDefinition` field, to their
original source code (for example, Dockerfile commands). The `source.locations`
field contains the ranges of all the Dockerfile commands ran in an LLB step.
`source.infos` array contains the source code itself. This mapping is present
if the BuildKit frontend provided it when creating the LLB definition.

#### layers

Only included with `mode=max`.

Defines the layer mapping of LLB build step mounts defined in
`buildDefinition.internalParameters.buildConfig.llbDefinition` to the OCI
descriptors of equivalent layers. This mapping is present if the layer data was
available, usually when attestation is for an image or if the build step pulled
in image data as part of the build.

#### vcs

Included with `mode=min` and `mode=max`.

Defines optional metadata for the version control system used for the build. If
a build uses a remote context from Git repository, BuildKit extracts the details
of the version control system automatically and displays it in the
`buildDefinition.externalParameters.configSource` field. But if the build uses
a source from a local directory, the VCS information is lost even if the
directory contained a Git repository. In this case, the build client can send
additional `vcs:source` and `vcs:revision` build options and BuildKit will add
them to the provenance attestations as extra metadata. Note that, contrary to
the `buildDefinition.externalParameters.configSource` field, BuildKit doesn't
verify the `vcs` values, and as such they can't be trusted and should only be
used as a metadata hint.

### runDetails.metadata.buildkit_hermetic

- Ref: [https://slsa.dev/spec/v1.1/provenance#extension-fields](https://slsa.dev/spec/v1.1/provenance#extension-fields)
- Included with `mode=min` and `mode=max`.

This extension field is set to true if the build was hermetic and did not access
the network. In Dockerfiles, a build is hermetic if it does not use `RUN`
commands or disables network with `--network=none` flag.

```json
"runDetails": {
      "metadata": {
        "buildkit_hermetic": true,
        ...
      },
    }
```

### runDetails.metadata.buildkit_completeness

- Ref: [https://slsa.dev/spec/v1.1/provenance#extension-fields](https://slsa.dev/spec/v1.1/provenance#extension-fields)
- Included with `mode=min` and `mode=max`.

This extension field defines if the provenance information is complete. It is
similar to `metadata.completeness` field in SLSA v0.2.

`buildkit_completeness.request` is true if all the build arguments are included
in the `buildDefinition.externalParameters.request` field. When building with
`min` mode, the build arguments are not included in the provenance information
and request is not complete. Request is also not complete on direct LLB builds
that did not use a frontend.

`buildkit_completeness.resolvedDependencies` is true if
`buildDefinition.resolvedDependencies` field includes all the dependencies of
the build. When building from un-tracked source in a local directory, the
dependencies are not complete, while when building from a remote Git repository
all dependencies can be tracked by BuildKit and
`buildkit_completeness.resolvedDependencies` is true.

```json
"runDetails": {
      "metadata": {
        "buildkit_completeness": {
          "request": true,
          "resolvedDependencies": true
        },
        ...
      },
    }
```

### runDetails.metadata.buildkit_reproducible

- Ref: [https://slsa.dev/spec/v1.1/provenance#extension-fields](https://slsa.dev/spec/v1.1/provenance#extension-fields)
- Included with `mode=min` and `mode=max`.

This extension field defines if the build result is supposed to be byte-by-byte
reproducible. It is similar to `metadata.reproducible` field in SLSA v0.2. This
value can be set by the user with the `reproducible=true` attestation parameter.

```json
"runDetails": {
      "metadata": {
        "buildkit_reproducible": false,
        ...
      },
    }
```

## SLSA v0.2

### builder.id

- Ref: [https://slsa.dev/spec/v0.2/provenance#builder.id](https://slsa.dev/spec/v0.2/provenance#builder.id)
- Included with `mode=min` and `mode=max`.

The field is set to the URL of the build, if available.

```json
"builder": {
      "id": "https://github.com/docker/buildx/actions/runs/3709599520"
    },
```

> Note
>
> This value can be set using the `builder-id` attestation parameter.

### buildType

- Ref: [https://slsa.dev/spec/v0.2/provenance#buildType](https://slsa.dev/spec/v0.2/provenance#buildType)
- Included with `mode=min` and `mode=max`.

The `buildType` field is set to `https://mobyproject.org/buildkit@v1` and can be
used to determine the structure of the provenance content.

```json
"buildType": "https://mobyproject.org/buildkit@v1",
```

### invocation.configSource

- Ref: [https://slsa.dev/spec/v0.2/provenance#invocation.configSource](https://slsa.dev/spec/v0.2/provenance#invocation.configSource)
- Included with `mode=min` and `mode=max`.

Describes the config that initialized the build.

```json
"invocation": {
      "configSource": {
        "uri": "https://github.com/moby/buildkit.git#refs/tags/v0.11.0",
        "digest": {
          "sha1": "4b220de5058abfd01ff619c9d2ff6b09a049bea0"
        },
        "entryPoint": "Dockerfile"
      },
      ...
    },
```

For builds initialized from a remote context, like a Git or HTTP URL, this
object defines the context URL and its immutable digest in the `uri` and
`digest` fields. For builds using a local frontend, such as a Dockerfile, the
`entryPoint` field defines the path for the frontend file that initialized the
build (`filename` frontend option).

### invocation.parameters

- Ref: [https://slsa.dev/spec/v0.2/provenance#invocation.parameters](https://slsa.dev/spec/v0.2/provenance#invocation.parameters)
- Partially included with `mode=min`.

Describes build inputs passed to the build.

```json
"invocation": {
      "parameters": {
        "frontend": "gateway.v0",
        "args": {
          "build-arg:BUILDKIT_CONTEXT_KEEP_GIT_DIR": "1",
          "label:FOO": "bar",
          "source": "docker/dockerfile-upstream:master",
          "target": "release"
        },
        "secrets": [
          {
            "id": "GIT_AUTH_HEADER",
            "optional": true
          },
          ...
        ],
        "ssh": [],
        "locals": []
      },
      ...
    },
```

The following fields are included with both `mode=min` and `mode=max`:

- `locals` lists any local sources used in the build, including the build
  context and frontend file.
- `frontend` defines type of BuildKit frontend used for the build. Currently,
  this can be `dockerfile.v0` or `gateway.v0`.
- `args` defines the build arguments passed to the BuildKit frontend.
  The keys inside the `args` object reflect the options as BuildKit receives
  them. For example, `build-arg` and `label` prefixes are used for build
  arguments and labels, and `target` key defines the target stage that was
  built. The `source` key defines the source image for the Gateway frontend, if
  used.

The following fields are only included with `mode=max`:

- `secrets` defines secrets used during the build. Note that actual secret
  values are not included.
- `ssh` defines the ssh forwards used during the build.

### invocation.environment

- Ref: [https://slsa.dev/spec/v0.2/provenance#invocation.environment](https://slsa.dev/spec/v0.2/provenance#invocation.environment)
- Included with `mode=min` and `mode=max`.

```json
"invocation": {
      "environment": {
        "platform": "linux/amd64"
      },
      ...
    },
```

The only value BuildKit currently sets is the `platform` of the current build
machine. Note that this is not necessarily the platform of the build result that
can be determined from the `in-toto` subject field.

### materials

- Ref: [https://slsa.dev/spec/v0.2/provenance#materials](https://slsa.dev/spec/v0.2/provenance#materials)
- Included with `mode=min` and `mode=max`.

Defines all the external artifacts that were part of the build. The value
depends on the type of artifact:

- The URL of Git repositories containing source code for the image
- HTTP URLs if you are building from a remote tarball, or that was included
  using an `ADD` command in Dockerfile
- Any Docker images used during the build

The URLs to the Docker images will be in
[Package URL](https://github.com/package-url/purl-spec) format.

All the build materials will include the immutable checksum of the artifact.
When building from a mutable tag, you can use the digest information to
determine if the artifact has been updated compared to when the build ran.

```json
"materials": [
      {
        "uri": "pkg:docker/alpine@3.17?platform=linux%2Famd64",
        "digest": {
          "sha256": "8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4"
        }
      },
      {
        "uri": "https://github.com/moby/buildkit.git#refs/tags/v0.11.0",
        "digest": {
          "sha1": "4b220de5058abfd01ff619c9d2ff6b09a049bea0"
        }
      },
      ...
    ],
```

### buildConfig

- Ref: [https://slsa.dev/spec/v0.2/provenance#buildConfig](https://slsa.dev/spec/v0.2/provenance#buildConfig)
- Only included with `mode=max`.

Defines the build steps performed during the build.

BuildKit internally uses LLB definition to execute the build steps. The LLB
definition of the build steps is defined in `buildConfig.llbDefinition` field.

Each LLB step is the JSON definition of the
[LLB ProtoBuf API](https://github.com/moby/buildkit/blob/v0.10.0/solver/pb/ops.proto).
The dependencies for a vertex in the LLB graph can be found in the `inputs`
field for every step.

```json
"buildConfig": {
    "llbDefinition": [
      {
        "id": "step0",
        "op": {
          "Op": {
            "exec": {
              "meta": {
                "args": [
                  "/bin/sh",
                  "-c",
                  "go build ."
                ],
                "env": [
                  "PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                  "GOPATH=/go",
                  "GOFLAGS=-mod=vendor",
                ],
                "cwd": "/src",
              },
              "mounts": [...]
            }
          },
          "platform": {...},
        },
        "inputs": [
          "step8:0",
          "step2:0",
        ]
      },
      ...
    ]
  },
```

### metadata.buildInvocationId

- Ref: [https://slsa.dev/spec/v0.2/provenance#buildInvocationId](https://slsa.dev/spec/v0.2/provenance#buildInvocationId)
- Included with `mode=min` and `mode=max`.

Unique identifier for the build invocation. When building a multi-platform image
with a single build request, this value will be the shared by all the platform
versions of the image.

```json
"metadata": {
      "buildInvocationID": "rpv7a389uzil5lqmrgwhijwjz",
      ...
    },
```

### metadata.buildStartedOn

- Ref: [https://slsa.dev/spec/v0.2/provenance#buildStartedOn](https://slsa.dev/spec/v0.2/provenance#buildStartedOn)
- Included with `mode=min` and `mode=max`.

Timestamp when the build started.

```json
"metadata": {
      "buildStartedOn": "2021-11-17T15:00:00Z",
      ...
    },
```

### metadata.buildFinishedOn

- Ref: [https://slsa.dev/spec/v0.2/provenance#buildFinishedOn](https://slsa.dev/spec/v0.2/provenance#buildFinishedOn)
- Included with `mode=min` and `mode=max`.

Timestamp when the build finished.

```json
"metadata": {
      "buildFinishedOn": "2021-11-17T15:01:00Z",
      ...
    },
```

### metadata.completeness

- Ref: [https://slsa.dev/spec/v0.2/provenance#metadata.completeness](https://slsa.dev/spec/v0.2/provenance#metadata.completeness)
- Included with `mode=min` and `mode=max`.

Defines if the provenance information is complete.

`completeness.parameters` is true if all the build arguments are included in the
`parameters` field. When building with `min` mode, the build arguments are not
included in the provenance information and parameters are not complete.
Parameters are also not complete on direct LLB builds that did not use a
frontend.

`completeness.environment` is always true for BuildKit builds.

`completeness.materials` is true if `materials` field includes all the
dependencies of the build. When building from un-tracked source in a local
directory, the materials are not complete, while when building from a remote Git
repository all materials can be tracked by BuildKit and `completeness.materials`
is true.

```json
"metadata": {
      "completeness": {
        "parameters": true,
        "environment": true,
        "materials": true
      },
      ...
    },
```

### metadata.reproducible

- Ref: [https://slsa.dev/spec/v0.2/provenance#metadata.reproducible](https://slsa.dev/spec/v0.2/provenance#metadata.reproducible)
- Included with `mode=min` and `mode=max`.

Defines if the build result is supposed to be byte-by-byte reproducible. This
value can be set by the user with the `reproducible=true` attestation parameter.

```json
"metadata": {
      "reproducible": false,
      ...
    },
```

### metadata.https://mobyproject.org/buildkit@v1#hermetic

Included with `mode=min` and `mode=max`.

This extension field is set to true if the build was hermetic and did not access
the network. In Dockerfiles, a build is hermetic if it does not use `RUN`
commands or disables network with `--network=none` flag.

```json
"metadata": {
      "https://mobyproject.org/buildkit@v1#hermetic": true,
      ...
    },
```

### metadata.https://mobyproject.org/buildkit@v1#metadata

Partially included with `mode=min`.

This extension field defines BuildKit-specific additional metadata that is not
part of the SLSA provenance spec.

```json
"metadata": {
      "https://mobyproject.org/buildkit@v1#metadata": {
        "source": {...},
        "layers": {...},
        "vcs": {...},
      },
      ...
    },
```

#### source

Only included with `mode=max`.

Defines a source mapping of LLB build steps, defined in the
`buildConfig.llbDefinition` field, to their original source code (for example,
Dockerfile commands). The `source.locations` field contains the ranges of all
the Dockerfile commands ran in an LLB step. `source.infos` array contains the
source code itself. This mapping is present if the BuildKit frontend provided it
when creating the LLB definition.

#### layers

Only included with `mode=max`.

Defines the layer mapping of LLB build step mounts defined in
`buildConfig.llbDefinition` to the OCI descriptors of equivalent layers. This
mapping is present if the layer data was available, usually when attestation is
for an image or if the build step pulled in image data as part of the build.

#### vcs

Included with `mode=min` and `mode=max`.

Defines optional metadata for the version control system used for the build. If
a build uses a remote context from Git repository, BuildKit extracts the details
of the version control system automatically and displays it in the
`invocation.configSource` field. But if the build uses a source from a local
directory, the VCS information is lost even if the directory contained a Git
repository. In this case, the build client can send additional `vcs:source` and
`vcs:revision` build options and BuildKit will add them to the provenance
attestations as extra metadata. Note that, contrary to the
`invocation.configSource` field, BuildKit doesn't verify the `vcs` values, and
as such they can't be trusted and should only be used as a metadata hint.

---

# Provenance attestations

> Provenance build attestations describe how and where your image was built.

# Provenance attestations

   Table of contents

---

The provenance attestations include facts about the build process, including
details such as:

- Build timestamps
- Build parameters and environment
- Version control metadata
- Source code details
- Materials (files, scripts) consumed during the build

By default, provenance attestations follow the
[SLSA provenance schema, version 0.2](https://slsa.dev/spec/v0.2/provenance#schema).
You can optionally enable [SLSA Provenance v1](https://slsa.dev/spec/v1.1/provenance#schema)
using [theversionparameter](#version).

For more information about how BuildKit populates these provenance properties, refer to
[SLSA definitions](https://docs.docker.com/build/metadata/attestations/slsa-definitions/).

## Create provenance attestations

To create a provenance attestation, pass the `--attest type=provenance` option
to the `docker buildx build` command:

```console
$ docker buildx build --tag <namespace>/<image>:<version> \
    --attest type=provenance,mode=[min,max],version=[v0.2,v1] .
```

Alternatively, you can use the shorthand `--provenance=true` option instead of `--attest type=provenance`.
To specify the `mode` or `version` parameters using the shorthand option, use:
`--provenance=mode=max,version=v1`.

For an example on how to add provenance attestations with GitHub Actions, see
[Add attestations with GitHub Actions](https://docs.docker.com/build/ci/github-actions/attestations/).

## Mode

You can use the `mode` parameter to define the level of detail to be included in
the provenance attestation. Supported values are `mode=min` (default) and
`mode=max`.

### Min

In `min` mode, the provenance attestations include a minimal set of information,
such as:

- Build timestamps
- The frontend used
- Build materials
- Source repository and revision
- Build platform
- Reproducibility

Values of build arguments, the identities of secrets, and rich layer metadata is
not included `mode=min`. The `min`-level provenance is safe to use for all
builds, as it doesn't leak information from any part of the build environment.

The following JSON example shows the information included in a provenance
attestations created using the `min` mode:

```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/docker/dockerfile@1",
        "digest": {
          "sha256": "9ba7531bd80fb0a858632727cf7a112fbfd19b17e94c4e84ced81e24ef1a0dbc"
        }
      },
      {
        "uri": "pkg:docker/golang@1.19.4-alpine?platform=linux%2Farm64",
        "digest": {
          "sha256": "a9b24b67dc83b3383d22a14941c2b2b2ca6a103d805cac6820fd1355943beaf1"
        }
      }
    ],
    "invocation": {
      "configSource": { "entryPoint": "Dockerfile" },
      "parameters": {
        "frontend": "gateway.v0",
        "args": {
          "cmdline": "docker/dockerfile:1",
          "source": "docker/dockerfile:1",
          "target": "binaries"
        },
        "locals": [{ "name": "context" }, { "name": "dockerfile" }]
      },
      "environment": { "platform": "linux/arm64" }
    },
    "metadata": {
      "buildInvocationID": "c4a87v0sxhliuewig10gnsb6v",
      "buildStartedOn": "2022-12-16T08:26:28.651359794Z",
      "buildFinishedOn": "2022-12-16T08:26:29.625483253Z",
      "reproducible": false,
      "completeness": {
        "parameters": true,
        "environment": true,
        "materials": false
      },
      "https://mobyproject.org/buildkit@v1#metadata": {
        "vcs": {
          "revision": "a9ba846486420e07d30db1107411ac3697ecab68",
          "source": "git@github.com:<org>/<repo>.git"
        }
      }
    }
  }
}
```

### Max

The `max` mode includes all of the information included in the `min` mode, as
well as:

- The LLB definition of the build. These show the exact steps taken to produce
  the image.
- Information about the Dockerfile, including a full base64-encoded version of
  the file.
- Source maps describing the relationship between build steps and image layers.

When possible, you should prefer `mode=max` as it contains significantly more
detailed information for analysis.

> Warning
>
> Note that `mode=max` exposes the values of
> [build arguments](https://docs.docker.com/reference/cli/docker/buildx/build/#build-arg).
>
>
>
> If you're misusing build arguments to pass credentials, authentication
> tokens, or other secrets, you should refactor your build to pass the secrets using
> [secret mounts](https://docs.docker.com/reference/cli/docker/buildx/build/#secret) instead.
> Secret mounts don't leak outside of the build and are never included in provenance attestations.

## Version

The `version` parameter lets you specify which SLSA provenance schema version
to use. Supported values are `version=v0.2` (default) and `version=v1`.

To use SLSA Provenance v1:

```console
$ docker buildx build --tag <namespace>/<image>:<version> \
    --attest type=provenance,mode=max,version=v1 .
```

For more information about SLSA Provenance v1, see the
[SLSA specification](https://slsa.dev/spec/v1.1/provenance). To see the
difference between SLSA v0.2 and v1 provenance attestations, refer to
[SLSA definitions](https://docs.docker.com/build/metadata/attestations/slsa-definitions/)

## Inspecting Provenance

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

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

```console
$ docker buildx imagetools inspect <namespace>/<image>:<version> \
    --format "{{ json .Provenance.SLSA }}"
{
  "buildType": "https://mobyproject.org/buildkit@v1",
  ...
}
```

You can also construct more complex expressions using the full functionality of
Go templates. For example, for provenance generated with `mode=max`, you can
extract the full source code of the Dockerfile used to build the image:

```console
$ docker buildx imagetools inspect <namespace>/<image>:<version> \
    --format '{{ range (index .Provenance.SLSA.metadata "https://mobyproject.org/buildkit@v1#metadata").source.infos }}{{ if eq .filename "Dockerfile" }}{{ .data }}{{ end }}{{ end }}' | base64 -d
FROM ubuntu:24.04
RUN apt-get update
...
```

## Provenance attestation example

The following example shows what a JSON representation of a provenance
attestation with `mode=max` looks like:

```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/docker/dockerfile@1",
        "digest": {
          "sha256": "9ba7531bd80fb0a858632727cf7a112fbfd19b17e94c4e84ced81e24ef1a0dbc"
        }
      },
      {
        "uri": "pkg:docker/golang@1.19.4-alpine?platform=linux%2Farm64",
        "digest": {
          "sha256": "a9b24b67dc83b3383d22a14941c2b2b2ca6a103d805cac6820fd1355943beaf1"
        }
      }
    ],
    "buildConfig": {
      "llbDefinition": [
        {
          "id": "step4",
          "op": {
            "Op": {
              "exec": {
                "meta": {
                  "args": ["/bin/sh", "-c", "go mod download -x"],
                  "env": [
                    "PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                    "GOLANG_VERSION=1.19.4",
                    "GOPATH=/go",
                    "CGO_ENABLED=0"
                  ],
                  "cwd": "/src"
                },
                "mounts": [
                  { "input": 0, "dest": "/", "output": 0 },
                  {
                    "input": -1,
                    "dest": "/go/pkg/mod",
                    "output": -1,
                    "mountType": 3,
                    "cacheOpt": { "ID": "//go/pkg/mod" }
                  },
                  {
                    "input": 1,
                    "selector": "/go.mod",
                    "dest": "/src/go.mod",
                    "output": -1,
                    "readonly": true
                  },
                  {
                    "input": 1,
                    "selector": "/go.sum",
                    "dest": "/src/go.sum",
                    "output": -1,
                    "readonly": true
                  }
                ]
              }
            },
            "platform": { "Architecture": "arm64", "OS": "linux" },
            "constraints": {}
          },
          "inputs": ["step3:0", "step1:0"]
        }
      ]
    },
    "metadata": {
      "buildInvocationID": "edf52vxjyf9b6o5qd7vgx0gru",
      "buildStartedOn": "2022-12-15T15:38:13.391980297Z",
      "buildFinishedOn": "2022-12-15T15:38:14.274565297Z",
      "reproducible": false,
      "completeness": {
        "parameters": true,
        "environment": true,
        "materials": false
      },
      "https://mobyproject.org/buildkit@v1#metadata": {
        "vcs": {
          "revision": "a9ba846486420e07d30db1107411ac3697ecab68-dirty",
          "source": "git@github.com:<org>/<repo>.git"
        },
        "source": {
          "locations": {
            "step4": {
              "locations": [
                {
                  "ranges": [
                    { "start": { "line": 5 }, "end": { "line": 5 } },
                    { "start": { "line": 6 }, "end": { "line": 6 } },
                    { "start": { "line": 7 }, "end": { "line": 7 } },
                    { "start": { "line": 8 }, "end": { "line": 8 } }
                  ]
                }
              ]
            }
          },
          "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": "s4j58ngehdal1b5hn7msiqaqe",
                          "local.sharedkeyhint": "dockerfile"
                        }
                      }
                    },
                    "constraints": {}
                  }
                },
                { "id": "step1", "op": { "Op": null }, "inputs": ["step0:0"] }
              ]
            }
          ]
        },
        "layers": {
          "step2:0": [
            [
              {
                "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                "digest": "sha256:261da4162673b93e5c0e7700a3718d40bcc086dbf24b1ec9b54bca0b82300626",
                "size": 3259190
              },
              {
                "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                "digest": "sha256:bc729abf26b5aade3c4426d388b5ea6907fe357dec915ac323bb2fa592d6288f",
                "size": 286218
              },
              {
                "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                "digest": "sha256:7f1d6579712341e8062db43195deb2d84f63b0f2d1ed7c3d2074891085ea1b56",
                "size": 116878653
              },
              {
                "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                "digest": "sha256:652874aefa1343799c619d092ab9280b25f96d97939d5d796437e7288f5599c9",
                "size": 156
              }
            ]
          ]
        }
      }
    }
  }
}
```

---

# Build attestations

> Introduction to SBOM and provenance attestations with Docker Build, what they are, and why they exist

# Build attestations

   Table of contents

---

Build attestations describe how an image was built, and what it contains. The
attestations are created at build-time by BuildKit, and become attached to the
final image as metadata.

The purpose of attestations is to make it possible to inspect an image and see
where it comes from, who created it and how, and what it contains. This enables
you to make informed decisions about how an image impacts the supply chain security
of your application. It also enables the use of policy engines for validating
images based on policy rules you've defined.

Two types of build attestations are available:

- Software Bill of Material (SBOM): list of software artifacts that an image
  contains, or that were used to build the image.
- Provenance: how an image was built.

## Purpose of attestations

The use of open source and third-party packages is more widespread than ever
before. Developers share and reuse code because it helps increase productivity,
allowing teams to create better products, faster.

Importing and using code created elsewhere without vetting it introduces a
severe security risk. Even if you do review the software that you consume, new
zero-day vulnerabilities are frequently discovered, requiring development teams
take action to remediate them.

Build attestations make it easier to see the contents of an image, and where it
comes from. Use attestations to analyze and decide whether to use an image, or
to see if images you are already using are exposed to vulnerabilities.

## Creating attestations

When you build an image with `docker buildx build`, you can add attestation
records to the resulting image using the `--provenance` and `--sbom` options.
You can opt in to add either the SBOM or provenance attestation type, or both.

```console
$ docker buildx build --sbom=true --provenance=true .
```

> Note
>
> The default image store doesn't support attestations. If you're using the
> default image store and you build an image using the default `docker` driver,
> or using a different driver with the `--load` flag, the attestations are
> lost.
>
>
>
> To make sure the attestations are preserved, you can:
>
>
>
> - Use a `docker-container` driver with the `--push` flag to push the image to
>   a registry directly.
> - Enable the
>   [containerd image store](https://docs.docker.com/desktop/features/containerd/).

> Note
>
> Provenance attestations are enabled by default, with the `mode=min` option.
> You can disable provenance attestations using the `--provenance=false` flag,
> or by setting the
> [BUILDX_NO_DEFAULT_ATTESTATIONS](https://docs.docker.com/build/building/variables/#buildx_no_default_attestations) environment variable.
>
>
>
> Using the `--provenance=true` flag attaches provenance attestations with `mode=min`
> by default. See [Provenance attestation](https://docs.docker.com/build/metadata/attestations/slsa-provenance/) for more details.

BuildKit generates the attestations when building the image. The attestation
records are wrapped in the in-toto JSON format and attached to the image
index in a manifest for the final image.

## Storage

BuildKit produces attestations in the [in-toto format](https://github.com/in-toto/attestation),
as defined by the [in-toto framework](https://in-toto.io/),
a standard supported by the Linux Foundation.

Attestations attach to images as a manifest in the image index. The data records
of the attestations are stored as JSON blobs.

Because attestations attach to images as a manifest, it means that you can
inspect the attestations for any image in a registry without having to pull the
whole image.

All BuildKit exporters support attestations. The `local` and `tar` can't save
the attestations to an image manifest, since it's outputting a directory of
files or a tarball, not an image. Instead, these exporters write the
attestations to one or more JSON files in the root directory of the export.

## Example

The following example shows a truncated in-toto JSON representation of an SBOM
attestation.

```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-15T11:47:54.546747383Z",
      "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-da0f600b-7f0a-4de0-8432-f83703e6bc4f",
    "name": "/run/src/core",
    // list of files that the image contains, e.g.:
    "files": [
      {
        "SPDXID": "SPDXRef-1ac501c94e2f9f81",
        "comment": "layerID: sha256:9b18e9b68314027565b90ff6189d65942c0f7986da80df008b8431276885218e",
        "fileName": "/bin/busybox",
        "licenseConcluded": "NOASSERTION"
      }
    ],
    // list of packages that were identified for this image:
    "packages": [
      {
        "name": "busybox",
        "originator": "Person: Sören Tempel <soeren+alpine@soeren-tempel.net>",
        "sourceInfo": "acquired package info from APK DB: lib/apk/db/installed",
        "versionInfo": "1.35.0-r17",
        "SPDXID": "SPDXRef-980737451f148c56",
        "description": "Size optimized toolbox of many common UNIX utilities",
        "downloadLocation": "https://busybox.net/",
        "licenseConcluded": "GPL-2.0-only",
        "licenseDeclared": "GPL-2.0-only"
        // ...
      }
    ],
    // files-packages relationship
    "relationships": [
      {
        "relatedSpdxElement": "SPDXRef-1ac501c94e2f9f81",
        "relationshipType": "CONTAINS",
        "spdxElementId": "SPDXRef-980737451f148c56"
      },
      ...
    ],
    "spdxVersion": "SPDX-2.2"
  }
}
```

To deep-dive into the specifics about how attestations are stored, see
[Image Attestation Storage (BuildKit)](https://docs.docker.com/build/metadata/attestations/attestation-storage/).

## Attestation manifest format

Attestations are stored as manifests, referenced by the image's index. Each
*attestation manifest* refers to a single *image manifest* (one
platform-variant of the image). Attestation manifests contain a single layer,
the "value" of the attestation.

The following example shows the structure of an attestation manifest:

```json
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.manifest.v1+json",
  "config": {
    "mediaType": "application/vnd.oci.image.config.v1+json",
    "size": 167,
    "digest": "sha256:916d7437a36dd0e258e64d9c5a373ca5c9618eeb1555e79bd82066e593f9afae"
  },
  "layers": [
    {
      "mediaType": "application/vnd.in-toto+json",
      "size": 1833349,
      "digest": "sha256:3138024b98ed5aa8e3008285a458cd25a987202f2500ce1a9d07d8e1420f5491",
      "annotations": {
        "in-toto.io/predicate-type": "https://spdx.dev/Document"
      }
    }
  ]
}
```

### Attestations as OCI artifacts

You can configure the format of the attestation manifest using the
[oci-artifactoption](https://docs.docker.com/build/exporters/image-registry/#synopsis)
for the `image` and `registry` exporters. If set to `true`, the structure of
the attestation manifest changes as follows:

- An `artifactType` field is added to the attestation manifest, with a value of `application/vnd.docker.attestation.manifest.v1+json`.
- The `config` field is an [empty descriptor](https://github.com/opencontainers/image-spec/blob/main/manifest.md#guidance-for-an-empty-descriptor) instead of a "dummy" config.
- A `subject` field is also added, pointing to the image manifest that the attestation refers to.

The following example shows an attestation with the OCI artifact format:

```json
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.manifest.v1+json",
  "artifactType": "application/vnd.docker.attestation.manifest.v1+json",
  "config": {
    "mediaType": "application/vnd.oci.empty.v1+json",
    "size": 2,
    "digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
    "data": "e30="
  },
  "layers": [
    {
      "mediaType": "application/vnd.in-toto+json",
      "size": 2208,
      "digest": "sha256:6d2f2c714a6bee3cf9e4d3cb9a966b629efea2dd8556ed81f19bd597b3325286",
      "annotations": {
        "in-toto.io/predicate-type": "https://slsa.dev/provenance/v0.2"
      }
    }
  ],
  "subject": {
    "mediaType": "application/vnd.oci.image.manifest.v1+json",
    "size": 1054,
    "digest": "sha256:bc2046336420a2852ecf915786c20f73c4c1b50d7803aae1fd30c971a7d1cead",
    "platform": {
      "architecture": "amd64",
      "os": "linux"
    }
  }
}
```

## What's next

Learn more about the available attestation types and how to use them:

- [Provenance](https://docs.docker.com/build/metadata/attestations/slsa-provenance/)
- [SBOM](https://docs.docker.com/build/metadata/attestations/sbom/)

---

# Built

> Buildx includes built-in helper functions to make writing policies easier

# Built-in functions

   Table of contents

---

Buildx provides built-in functions, in addition to the [Rego
built-ins](#rego-built-in-functions), to extend Rego policies with
Docker-specific operations like loading local files, verifying Git signatures,
and pinning image digests.

## Rego built-in functions

The functions [documented on this page](#buildx-built-in-functions) are
Buildx-specific functions, distinct from [Rego's standard built-in
functions](https://www.openpolicyagent.org/docs/policy-language#built-in-functions)

Buildx also supports standard Rego built-in functions, but only a subset. To
see the exact list of supported functions, refer to the Buildx [source
code](https://github.com/docker/buildx/blob/master/policy/builtins.go).

## Buildx built-in functions

Buildx provides the following custom built-in functions for policy development:

- [print](#print)
- [load_json](#load_json)
- [verify_git_signature](#verify_git_signature)
- [pin_image](#pin_image)

### print

Outputs debug information during policy evaluation.

Parameters:

- Any number of values to print

Returns: The values (pass-through)

Example:

```rego
allow if {
    input.image.repo == "alpine"
    print("Allowing alpine image:", input.image.tag)
}
```

Debug output appears when building with `--progress=plain`.

### load_json

Loads and parses JSON data from local files in the build context.

Parameters:

- `filename` (string) - Path to JSON file relative to policy directory

Returns: Parsed JSON data as Rego value

Example:

```rego
# Load approved versions from external file
approved_versions = load_json("versions.json")

allow if {
    input.image.repo == "alpine"
    some version in approved_versions.alpine
    input.image.tag == version
}
```

File structure:

```text
project/
├── Dockerfile
├── Dockerfile.rego
└── versions.json
```

versions.json:

```json
{
  "alpine": ["3.19", "3.20"],
  "golang": ["1.21", "1.22"]
}
```

The JSON file must be in the same directory as the policy or in a
subdirectory accessible from the policy location.

### verify_git_signature

Verifies PGP signatures on Git commits or tags.

Parameters:

- `git_object` (object) - Either `input.git.commit` or `input.git.tag`
- `keyfile` (string) - Path to PGP public key file (relative to policy
  directory)

Returns: Boolean - `true` if signature is valid, `false` otherwise

Example:

```rego
# Require signed Git tags
allow if {
    input.git.tagName != ""
    verify_git_signature(input.git.tag, "maintainer.asc")
}

# Require signed commits
allow if {
    input.git.commit
    verify_git_signature(input.git.commit, "keys/team.asc")
}
```

Directory structure:

```text
project/
├── Dockerfile.rego
└── maintainer.asc          # PGP public key
```

Or with subdirectory:

```text
project/
├── Dockerfile.rego
└── keys/
    ├── maintainer.asc
    └── team.asc
```

Obtaining public keys:

```console
$ gpg --export --armor user@example.com > maintainer.asc
```

### pin_image

Pins an image to a specific digest, overriding the tag-based reference. Use
this to force builds to use specific image versions.

Parameters:

- `image_object` (object) - Must be `input.image` (the current image being
  evaluated)
- `digest` (string) - Target digest in format `sha256:...`

Returns: Boolean - `true` if pinning succeeds

Example:

```rego
# Pin alpine 3.19 to specific digest
alpine_3_19_digest = "sha256:4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412"

allow if {
    input.image.repo == "alpine"
    input.image.tag == "3.19"
    pin_image(input.image, alpine_3_19_digest)
}
```

Automatic digest replacement:

```rego
# Replace old digests with patched versions
replace_map = {
  "3.22.0": "3.22.2",
  "3.22.1": "3.22.2",
}

alpine_digests = {
  "3.22.0": "sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be023728e11715",
  "3.22.2": "sha256:4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412",
}

allow if {
    input.image.repo == "alpine"
    some old_version, new_version in replace_map
    input.image.checksum == alpine_digests[old_version]
    print("Replacing", old_version, "with", new_version)
    pin_image(input.image, alpine_digests[new_version])
}
```

This pattern automatically upgrades old image versions to patched releases.

## Next steps

- Browse complete examples: [Example policies](https://docs.docker.com/build/policies/examples/)
- Learn policy development workflow: [Using build policies](https://docs.docker.com/build/policies/usage/)
- Reference input fields: [Input reference](https://docs.docker.com/build/policies/inputs/)

---

# Debugging build policies

> Debug policies during development with inspection and testing tools

# Debugging build policies

   Table of contents

---

When policies don't work as expected, use the tools available to inspect policy
evaluation and understand what's happening. This guide covers the debugging
techniques and common gotchas.

## Quick reference

Essential debugging commands:

```console
# See complete input data during builds (recommended)
$ docker buildx build --progress=plain --policy log-level=debug .

# See policy checks and decisions
$ docker buildx build --progress=plain .

# Explore input structure for different sources
$ docker buildx policy eval --print .
$ docker buildx policy eval --print https://github.com/org/repo.git
$ docker buildx policy eval --print docker-image://alpine:3.19

# Test if policy allows a source
$ docker buildx policy eval .
```

## Policy output with--progress=plain

To see policy evaluation during builds, use `--progress=plain`:

```console
$ docker buildx build --progress=plain .
```

This shows all policy checks, decisions, and `print()` output. Without
`--progress=plain`, policy evaluation is silent unless there's an error.

```plaintext
#1 loading policies Dockerfile.rego
#1 0.010 checking policy for source docker-image://alpine:3.19 (linux/arm64)
#1 0.011 Dockerfile.rego:8: image: {"ref":"alpine:3.19","repo":"alpine","tag":"3.19"}
#1 0.012 policy decision for source docker-image://alpine:3.19: ALLOW
```

If a policy denies a source, you'll see:

```text
#1 0.012 policy decision for source docker-image://nginx:latest: DENY
ERROR: source "docker-image://nginx:latest" not allowed by policy
```

## Debug logging

For detailed debugging, add `--policy log-level=debug` to see the full input
JSON, unresolved fields, and policy responses:

```console
$ docker buildx build --progress=plain --policy log-level=debug .
```

This shows significantly more information than the default level, including the
complete input structure for each source without needing `print()` statements
in your policy.

Complete input JSON:

```text
#1 0.007 policy input: {
#1 0.007   "env": {
#1 0.007     "filename": "."
#1 0.007   },
#1 0.007   "image": {
#1 0.007     "ref": "docker.io/library/alpine:3.19",
#1 0.007     "host": "docker.io",
#1 0.007     "repo": "alpine",
#1 0.007     "fullRepo": "docker.io/library/alpine",
#1 0.007     "tag": "3.19",
#1 0.007     "platform": "linux/arm64",
#1 0.007     "os": "linux",
#1 0.007     "arch": "arm64"
#1 0.007   }
#1 0.007 }
```

Unresolved fields:

```text
#1 0.007 unknowns for policy evaluation: [input.image.checksum input.image.labels input.image.user input.image.volumes input.image.workingDir input.image.env input.image.hasProvenance input.image.signatures]
```

Policy response:

```text
#1 0.008 policy response: map[allow:true]
```

This detailed output is invaluable for understanding exactly what data your
policy receives and which fields are not yet resolved. Use debug logging when
developing policies to avoid needing extensive `print()` statements.

## Conditional debugging with print()

While `--policy log-level=debug` shows all input data automatically, the
`print()` function is useful for debugging specific rule logic and conditional
flows:

```rego
allow if {
    input.image
    print("Checking image:", input.image.repo, "isCanonical:", input.image.isCanonical)
    input.image.repo == "alpine"
    input.image.isCanonical
}
```

Use `print()` to debug conditional logic within rules or track which rules are
evaluating. For general input inspection during development, use `--policy log-level=debug` instead - it requires no policy modifications.

> Note
>
> Print statements only execute when their containing rule evaluates. A rule
> like `allow if { input.image; print(...) }` only prints for image inputs,
> not for Git repos, HTTP downloads, or local files.

## Common issues

### Full repository path or repository name

Symptom: Policy checking repository names doesn't match as expected.

Cause: Docker Hub images use `input.image.repo` for the short name
(`"alpine"`) but `input.image.fullRepo` includes the full path
(`"docker.io/library/alpine"`).

Solution:

```rego
# Match just the repo name (works for Docker Hub and other registries)
allow if {
    input.image
    input.image.repo == "alpine"
}

# Or match the full repository path
allow if {
    input.image
    input.image.fullRepo == "docker.io/library/alpine"
}
```

### Policy evaluation happens multiple times

Symptom: Build output shows the same source evaluated multiple times.

Cause: BuildKit may evaluate policies at different stages (reference
resolution, actual pull) or for different platforms.

This is normal behavior. Policies should be idempotent (produce same result
each time for the same input).

### Fields missing withpolicy eval --print

Symptom: `docker buildx policy eval --print` doesn't show expected fields
like `hasProvenance`, `labels`, or `checksum`.

Cause: `--print` shows only reference information by default, without
fetching from registries.

Solution: Use `--fields` to fetch specific metadata fields:

```console
$ docker buildx policy eval --print --fields image.labels docker-image://alpine:3.19
```

See [Using build policies](https://docs.docker.com/build/policies/usage/#testing-policies-with-policy-eval) for
details.

## Next steps

- See complete field reference: [Input reference](https://docs.docker.com/build/policies/inputs/)
- Review example policies: [Examples](https://docs.docker.com/build/policies/examples/)
- Learn policy usage patterns: [Using build policies](https://docs.docker.com/build/policies/usage/)
