To attest build provenance for a container image on GitHub, add GitHub's attest action after the image build, give the job id-token write, attestations write, contents read and packages write, pass the image name and its digest, and set push-to-registry. Consumers then check it with gh attestation verify.
What an attestation is
An attestation is a signed statement about an artifact: here, that this image digest was built by this workflow in this repository. It is a record of where something came from. It is not a statement that the image is free of vulnerabilities. For that, scan it. See what package provenance proves and what it does not.
Permissions the job needs
From GitHub's artifact attestations guide:
| Artifact type | Permissions |
|---|---|
| Binaries | id-token write, contents read, attestations write |
| Container images | The same, plus packages write |
Set them on the job, not the workflow. See least privilege GITHUB_TOKEN for a release workflow.
The step
- name: Generate artifact attestation
uses: actions/attest@v4
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
The guide says the image name must be fully qualified and must not include a tag. If you build with docker/build-push-action, you can take the digest from its digest output. That is why you attest the digest and not the tag. A tag can move; a digest cannot. See why sign the image digest, not the tag. Pin third party actions by commit SHA too, as in pin GitHub Actions to a SHA or a tag.
Verify it
For a container image, log in to the registry first, then run the oci form:
docker login ghcr.io
gh attestation verify oci://ghcr.io/ORGANIZATION_NAME/IMAGE_NAME:test -R ORGANIZATION_NAME/REPOSITORY_NAME
For a file, use the path form with the same repository flag. The guide notes these commands assume an online environment and points to a separate guide for offline verification.
Add an SBOM attestation
The guide says the action can attest an SBOM too, with SPDX or CycloneDX predicates, by adding the sbom-path input. To verify, add a predicate type flag with the SPDX document URL given in the guide. Create the SBOM with a tool of your choice. See attach an SBOM and signature to an image with OCI referrers.
Common mistakes
- Attesting a tag instead of a digest.
- Forgetting packages write, so push to the registry fails.
- Treating a verified attestation as proof the image is clean.
- Never running the verify command yourself. See verify your own release the way a user would.
Try it yourself
Click through it at your own pace, or open it full screen.
Click through the scan and compare the findings with what an attestation can and cannot tell you.
Safeguard scans container images and generates SBOMs; the free scan is at gold.safeguard.sh/scan.
Quick check
Does an attestation mean the image is secure?
No. It says where and how the image was built, not that its contents are free of flaws.
Why must I leave the tag off the subject name?
The guide says to use the fully qualified name without a tag, and to pass the digest separately.
Sources
Last reviewed: 19 October 2026.