adorsys / adorsys/status-list-server

Image provenance is self-asserted; no third-party-verifiable issuer

Open
#402 1 comment 0 reactions 1 assignee Claimed by @martcpp View on GitHub
Dominant language
Rust
Stars
22
Forks
5
Avg merge
2d 11h
Merged PRs (30d)
47

Description

## Summary

The image published by `deploy.yml` carries a BuildKit provenance attestation (`provenance: mode=max`). That attestation is integrity-protected the OCI index digest chain covers it, so it cannot be altered without changing the image digest.

It is not authenticity-protected. The `builder.id` field pointing at the Actions run is self-asserted: it is a JSON blob BuildKit wrote, with nothing binding it to the run that allegedly produced it. Anyone with push access to the GHCR package can push an index carrying a fabricated provenance manifest that inspects identically.

**The gap is "who said this," not "was this changed."** These are easy to conflate and the
distinction is the whole ticket.

## Why this matters here

This service is an authority other systems trust. A compromise of package push access
currently escalates to a compromise of everything downstream that pulls the image, because
no consumer can distinguish an image we built from one someone else pushed with a matching
provenance claim.

## The non-obvious part

`actions/attest-build-provenance` **does not sign the BuildKit attestation.**

It generates a *second, independent* provenance document over the same image digest via
Sigstore/Fulcio. Different content, different trust properties, different verification tool
(`gh attestation verify` vs `docker buildx imagetools inspect`). Both end up attached to
one image and nothing reconciles them.

Anyone picking this up cold will assume the work is enabling a flag. It is not.

## The actual decision

1. **Keep both** — accept two provenance statements about one image, and document which one
consumers should verify and what it means if they disagree.
2. **Set `provenance: false`** and let GitHub's be the only one — this undoes the explicit
`mode=max` pinning from the supply-chain PR, whose justification was that the BuildKit
default is repo-visibility-dependent and would silently degrade to `mode=min` if the repo
were ever flipped private. That argument has to be answered, not ignored.

Also to be decided rather than discovered: the repo is public, so `attest-build-provenance`
publishes to Rekor, a public transparency log. Probably fine. Should be a choice.

## Permissions note

The supply-chain PR **removed** `id-token: write` and `attestations: write` from the build
job, because BuildKit-native `sbom:`/`provenance:` write into the registry under the existing
`packages: write` and do not need them.

This ticket **adds them back**, because `actions/attest-build-provenance` does need them.

Both are correct. Recorded here so that reading the two diffs in sequence does not look like
one of them is a mistake.

## Out of scope

- Cosign keyless signing of the image itself (distinct from attestation provenance)
- Any admission-control / policy enforcement on verification — that is a consumer-side
decision and a separate ticket again

## Acceptance criteria

- [ ] Decision recorded (option 1 or 2 above) with reasoning, as an ADR
- [ ] Rekor / public transparency log implication explicitly accepted or rejected
- [ ] `docs/supply-chain.md` states which attestation a consumer should verify, with the
exact verification command
- [ ] Permissions scoped per-job, zizmor clean

eta 2days

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.