Skip to content

attest-docker.yml

Generate and attach security attestations (SLSA provenance and/or SBOM) to an already-built Docker image. Designed to run after build-docker.yml.

Inputs

InputTypeDescriptionRequiredDefault
IMAGE_NAMEstringFull image name including registry and path (e.g. ghcr.io/my-org/my-image). Normalized automatically.Yes-
DIGESTstringDigest of the image to attest (e.g. sha256:abc123...). Use the digest output of build-docker.yml.Yes-
PROVENANCEbooleanGenerate a SLSA provenance attestation for the imageNofalse
SBOMbooleanGenerate an SBOM (Software Bill of Materials) attestation for the imageNofalse
RUNS_ONstringRunner labels as JSON array (e.g., '["ubuntu-24.04"]' or '["self-hosted", "linux"]')No["ubuntu-24.04"]

Secrets

SecretDescriptionRequired
REGISTRY_USERNAMEUsername used to login into registry (not needed for ghcr.io)No
REGISTRY_PASSWORDPassword used to login into registry (not needed for ghcr.io)No

Permissions

ScopeAccessDescription
packageswritePush attestations to the registry
id-tokenwriteRequired to sign attestations via OIDC
attestationswriteRequired to create GitHub attestations

Notes

  • This workflow is designed to be called after build-docker.yml, using its digest and image outputs.
  • At least one of PROVENANCE or SBOM must be true for the job to perform a useful action.
  • SLSA Provenance: generates an attestation conforming to SLSA level 3, attached to the image in the registry.
  • SBOM: generates an SPDX SBOM via Trivy, then attests and attaches it to the image in the registry.
  • The image name is automatically normalized (lowercase, _ replaced with -) for OCI registry compatibility.
  • For ghcr.io, authentication uses github.token automatically; for other registries, provide REGISTRY_USERNAME and REGISTRY_PASSWORD as secrets.
  • Alternative: when using build-docker.yml in a matrix strategy, outputs from individual matrix jobs cannot be easily forwarded to this workflow. In that case, prefer enabling PROVENANCE and/or SBOM directly in build-docker.yml instead — each matrix job will attest its own image automatically.

Examples

After a build with provenance and SBOM

yaml
jobs:
  build:
    uses: this-is-tobi/github-workflows/.github/workflows/build-docker.yml@v0
    permissions:
      packages: write
      contents: read
    with:
      IMAGE_NAME: ghcr.io/my-org/my-app
      IMAGE_TAG: ${{ needs.release.outputs.version }}
      IMAGE_CONTEXT: ./
      IMAGE_DOCKERFILE: ./Dockerfile
      LATEST_TAG: true

  attest:
    uses: this-is-tobi/github-workflows/.github/workflows/attest-docker.yml@v0
    needs:
    - build
    permissions:
      packages: write
      id-token: write
      attestations: write
    with:
      IMAGE_NAME: ${{ needs.build.outputs.image }}
      DIGEST: ${{ needs.build.outputs.digest }}
      PROVENANCE: true
      SBOM: true

Provenance only

yaml
jobs:
  attest:
    uses: this-is-tobi/github-workflows/.github/workflows/attest-docker.yml@v0
    needs:
    - build
    permissions:
      packages: write
      id-token: write
      attestations: write
    with:
      IMAGE_NAME: ${{ needs.build.outputs.image }}
      DIGEST: ${{ needs.build.outputs.digest }}
      PROVENANCE: true

With a custom registry

yaml
jobs:
  attest:
    uses: this-is-tobi/github-workflows/.github/workflows/attest-docker.yml@v0
    needs:
    - build
    permissions:
      packages: write
      id-token: write
      attestations: write
    with:
      IMAGE_NAME: docker.io/my-org/my-image
      DIGEST: ${{ needs.build.outputs.digest }}
      PROVENANCE: true
      SBOM: true
    secrets:
      REGISTRY_USERNAME: ${{ secrets.DOCKER_USERNAME }}
      REGISTRY_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}