Skip to content
Français
Account: not signed in, sync available My learning
Select theme
Français

By updated

Improve this page

Attestations let you prove cryptographically where your artefacts come from: who built them, from which code, with which workflow. They are a key part of supply chain security.

What you will learn

  • Understand attestations and what they prove cryptographically
  • Tell apart a provenance attestation (SLSA) and an SBOM attestation
  • Generate an attestation for an artefact or a Docker image
  • Attest an SBOM alongside the provenance
  • Know where GitHub and Sigstore keep the attestations

What is an attestation?

An attestation is a signed document certifying information about an artefact:

{
"_type": "https://in-toto.io/Statement/v1",
"subject": [
{
"name": "my-app",
"digest": {
"sha256": "abc123..."
}
}
],
"predicateType": "https://slsa.dev/provenance/v1",
"predicate": {
"buildDefinition": {
"buildType": "https://actions.github.io/buildtypes/workflow/v1"
},
"runDetails": {
"builder": {
"id": "https://github.com/actions/runner"
}
}
}
}

What the attestation proves:

InformationValue
ArtefactSHA256 hash of the artefact
BuilderGitHub Actions runner
Repositoryowner/repo
CommitThe commit SHA
WorkflowFile and reference
SignerSigstore (Fulcio/Rekor)

Types of attestation

GitHub Actions produces two standard attestation types, provenance and SBOM, and allows custom attestations.

Provenance attestation (SLSA)

Proves how the artefact was built:

  • From which source code
  • With which workflow
  • With which build parameters

SBOM attestation

Proves what the artefact contains:

  • The list of dependencies
  • The exact versions
  • The licences

Custom attestation

You can add your own information:

  • Test results
  • Security scan results
  • Business metadata

Generating an attestation

The official actions/attest-build-provenance action generates and signs the attestation. The workflow needs three permissions: id-token, contents and attestations.

With actions/attest-build-provenance

This action produces a provenance attestation for any artefact file.

name: Build and Attest
on:
push:
branches: [main]
permissions:
id-token: write # To sign with Sigstore
contents: read
attestations: write # To publish the attestation
jobs:
build:
runs-on: ubuntu-24.04
steps:
- name: Check out the code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Build the artefact
run: |
npm ci
npm run build
tar -czf dist.tar.gz dist/
- name: Generate the attestation
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
with:
subject-path: dist.tar.gz

For a Docker image

For an image, the attestation targets the published digest and can be attached directly to the registry.

jobs:
build:
runs-on: ubuntu-24.04
permissions:
id-token: write
contents: read
attestations: write
packages: write
steps:
- name: Check out the code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Log in to GHCR
uses: docker/login-action@06fb636fac595d6fb4b28a5dfcb21a6f5091859c # v4.5.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push the image
id: build
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
push: true
tags: ghcr.io/${{ github.repository }}:${{ github.sha }}
- name: Generate the attestation
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
with:
subject-name: ghcr.io/${{ github.repository }}
subject-digest: ${{ steps.build.outputs.digest }}
push-to-registry: true

SBOM attestation

Generate an SBOM (Software Bill of Materials) then attest it, to prove the exact content of the artefact:

jobs:
sbom:
runs-on: ubuntu-24.04
permissions:
id-token: write
contents: read
attestations: write
steps:
- name: Check out the code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Generate the SBOM
uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
id: sbom
with:
format: spdx-json
output-file: sbom.spdx.json
- name: Attest the SBOM
uses: actions/attest-sbom@c604332985a26aa8cf1bdc465b92731239ec6b9e # v4.1.0
with:
subject-path: dist.tar.gz
sbom-path: sbom.spdx.json

Where are the attestations stored?

A generated attestation is kept in two places, which makes it both queryable and tamper-evident.

The GitHub Attestations API

Attestations are stored in GitHub and reachable through:

  • The REST API: GET /repos/{owner}/{repo}/attestations/{digest}
  • The CLI: gh attestation verify

The Sigstore transparency log

Attestations are also recorded in Rekor, the Sigstore transparency log. That guarantees they cannot be altered after the fact.

A complete workflow

Here is a full release workflow: build, SBOM, double attestation (provenance and SBOM), then publication.

name: Build, Attest and Release
on:
push:
tags:
- 'v*'
permissions:
id-token: write
contents: write
attestations: write
packages: write
jobs:
build:
runs-on: ubuntu-24.04
outputs:
digest: ${{ steps.build.outputs.digest }}
steps:
- name: Check out the code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Build the artefact
id: build
env:
REF_NAME: ${{ github.ref_name }}
run: |
npm ci
npm run build
tar -czf "my-app-$REF_NAME.tar.gz" dist/
echo "digest=$(sha256sum "my-app-$REF_NAME.tar.gz" | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"
- name: Generate the SBOM
uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
with:
format: spdx-json
output-file: sbom.spdx.json
- name: Attest the provenance
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
with:
subject-path: my-app-${{ github.ref_name }}.tar.gz
- name: Attest the SBOM
uses: actions/attest-sbom@c604332985a26aa8cf1bdc465b92731239ec6b9e # v4.1.0
with:
subject-path: my-app-${{ github.ref_name }}.tar.gz
sbom-path: sbom.spdx.json
- name: Create the release
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
files: |
my-app-${{ github.ref_name }}.tar.gz
sbom.spdx.json

Good practices

A few reflexes make sure your attestations genuinely secure the delivery chain.

1. Always attest the releases

Every distributed artefact must carry a provenance attestation; without one, the consumer cannot verify where it came from.

2. Attest the Docker images

For an image, push-to-registry: true attaches the attestation directly to the image in the registry.

- uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
with:
subject-name: ghcr.io/${{ github.repository }}
subject-digest: ${{ steps.build.outputs.digest }}
push-to-registry: true # Attaches the attestation to the image

3. Generate an SBOM as well

The provenance attestation says how the artefact was built; the SBOM says what it contains. The two are complementary.

4. Verify before deployment

An attestation is only worth something when it is verified on the consumer side. Before deploying an artefact, validate its provenance: see Verifying attestations.

Key points

  • An attestation is a signed document proving the origin of an artefact: source code, workflow, builder.
  • The provenance attestation (SLSA) says how the artefact was built; the SBOM attestation says what it contains.
  • actions/attest-build-provenance and actions/attest-sbom require the id-token: write and attestations: write permissions.
  • Attestations are signed through Sigstore and recorded in the Rekor transparency log, so they cannot be altered afterwards.
  • An attestation only protects you when it is verified before deployment.

For the full reference, see the official documentation on artifact attestations.

Check your understanding

Make sure the essentials of this guide are yours. The questions only cover what was explained here.

Knowledge check

Check what you have learned with this interactive quiz

6 questions
6 min
70% to pass

How it works

  • The timer starts when you click Start
  • Multiple choice, true/false and short answer questions
  • You can move between questions
  • Detailed results are shown at the end

Starts the quiz and the timer

Is this project useful to you?

The guides, courses, quizzes and labs stay free. If you use them regularly, you can contribute to their upkeep and development.

Become a supporting member (new tab) One-time support (new tab) Learn more

Follow the project on LinkedIn