Skip to content

ci: attach provenance and SBOM attestations to the published images - #8398

Open
kobihikri wants to merge 1 commit into
gogs:mainfrom
kobihikri:ci/image-provenance-sbom
Open

ci: attach provenance and SBOM attestations to the published images#8398
kobihikri wants to merge 1 commit into
gogs:mainfrom
kobihikri:ci/image-provenance-sbom

Conversation

@kobihikri

Copy link
Copy Markdown

Hi, and thanks for Gogs.

.github/workflows/docker.yml publishes the images to three registries — Docker Hub, ghcr.io and registry.digitalocean.com — across five build steps, but none of the pushed manifests carry a provenance or SBOM attestation. Someone pulling gogs/gogs:latest can see it exists; they cannot check that it was built by this workflow from this repository.

Gogs is self-hosted and the image is normally what people deploy directly, so the image is the artifact — there is no intermediate package manager doing any vouching along the way.

Worth saying up front that the security posture here is already better than most: every one of these steps is followed by a Trivy scan with exit-code: '1', so a vulnerable image genuinely fails the build rather than just printing a warning. This PR is the complementary half — Trivy answers "is there anything known-bad inside", provenance answers "did this come from where it claims".

The change is two lines on each of the five push: true steps:

        with:
          ...
          push: true
          provenance: mode=max
          sbom: true

I used BuildKit's own attestation support rather than a separate signing step, deliberately: each of your steps pushes one build to three registries at once, and BuildKit attaches the attestation to the image manifest, so all three get it with no extra plumbing and no second credential. It also means no permissions changecontents: read stays exactly as it is and nothing needs id-token.

Consumers can then check any tag with:

docker buildx imagetools inspect ghcr.io/gogs/gogs:latest --format '{{ json .Provenance }}'

Two caveats I would rather state than leave you to find:

  • mode=max records the full build including build arguments. That is usually what you want for a public image; if any build arg has ever been sensitive, provenance: true gives a smaller record.
  • Attestations add an extra manifest to the index. Docker Hub, GHCR and DigitalOcean's registry all support this, but it is the sort of thing worth knowing if a mirror ever sits in front of them.

No SLSA level claimed — the attestation is what BuildKit produces, and characterising the whole build is your call.

Disclosure: I used AI assistance to help spot this and prepare the change, and I read the workflow and all five push targets myself.

@kobihikri
kobihikri requested a review from unknwon as a code owner July 28, 2026 22:22
@kobihikri

Copy link
Copy Markdown
Author

Correction — I got a fact wrong in this PR, and I would rather flag it myself than let it sit.

I wrote that the pushed manifest "carries no provenance or SBOM attestation". That is half wrong, and the wrong half matters.

Provenance is already there. For public repositories, docker/build-push-action adds provenance attestations with mode=max by default — Docker's documentation states it plainly: "Public repos: provenance attestations with mode=max are automatically added". I checked published images and they do already carry attestation manifests. So the provenance: mode=max line in my diff makes existing behaviour explicit; it does not add anything new.

The SBOM is genuinely new. That part stands — the same page says "SBOM attestations aren't automatically added to the image", and sbom: true is what enables them.

I also wrote in the caveats that provenance: true gives "a smaller record". That is wrong as well: true resolves to max on a public repo, and the smaller setting is provenance: mode=min.

So the honest description of this PR is: it adds an SBOM attestation, and pins the provenance mode explicitly instead of relying on the default. Both are still defensible — an explicit line means the behaviour will not change quietly if the default ever does — but it is a smaller change than my description implied, and you should judge it on that basis rather than on what I originally wrote.

Happy to retitle and rewrite the description accordingly, or to close this if the SBOM alone is not worth the diff to you. Either is fine — just say which and I will act on it.

Apologies for the inaccuracy. It was caught by a maintainer reviewing the same change on another project, and they were right to.

context: .
platforms: linux/amd64
push: true
provenance: mode=max

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two ttl.sh steps push throwaway 7-day images only so Trivy can scan them, nobody consumes them as artifacts. Better to drop provenance/SBOM here and keep it on the real publish targets.

file: Dockerfile.next
platforms: linux/amd64
push: true
provenance: mode=max

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, this is the ttl.sh scan-only push. No consumer for these attestations.

@unknwon unknwon left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants