Skip to content

security: verify docs-builder :edge attestation in consumer workflows - #160

Open
cotti wants to merge 15 commits into
mainfrom
security/verify-edge-attestation
Open

security: verify docs-builder :edge attestation in consumer workflows#160
cotti wants to merge 15 commits into
mainfrom
security/verify-edge-attestation

Conversation

@cotti

@cotti cotti commented May 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Consumer-side follow-up to #159 (fix/hardening-batch) that closes the
loop on #518.
After #159, both consumer paths that pull ghcr.io/elastic/docs-builder:edge
already resolve the mutable tag to an immutable RepoDigest. This PR
adds the missing step: verifying the SLSA build-provenance attestation
that docs-builder's prerelease.yml mints on every push, so we don't
just trust that a digest is stable but also who produced it.

Issue addressed

# Issue Fix
1 #518 (consumer, part 2/2) .github/workflows/docs-deploy.yml (Pull and pin docs-builder image) and docs-builder/setup/action.yml (edge branch) now run gh attestation verify oci://${DIGEST} -R elastic/docs-builder between digest resolution and any further use of the image. -R elastic/docs-builder constrains the attestation issuer so an attacker cannot publish a self-signed attestation under their own repo and have it accepted. The consumer fails closed if the attestation is missing, malformed, or signed by an unexpected workflow.

Merge ordering

Do not merge this PR until all of the following have happened:

  1. security: harden docs-builder, changelog, and workflow trust boundaries #159 has merged.
  2. elastic/docs-builder#3329 (security/output-sanitizer) has merged.
  3. The next prerelease.yml run on docs-builder main has completed successfully and pushed a new :edge digest with its attestation to ghcr.io/elastic/docs-builder.

If merged earlier, every docs-deploy.yml run on every consumer repo will fail at the verify step because no signed :edge digest exists yet. That's the intended fail-closed behavior, but it would break deploys repo-wide.

This PR remains in draft until those prerequisites are met. Convert it to ready once a successful signed prerelease run is observable.

Test plan

  • After the producer ships and at least one signed :edge exists, run gh attestation verify oci://ghcr.io/elastic/docs-builder@<latest-edge-digest> -R elastic/docs-builder locally; it should succeed.
  • Open a same-repo docs PR after merge; the Pull and pin docs-builder image step should verify successfully before the container runs.
  • Temporarily point EDGE_IMAGE at a fork-built unsigned image in a scratch branch; the verification should fail closed with a clear error.

cotti and others added 7 commits May 12, 2026 05:53
Add `gh attestation verify` to both consumer paths that pull
`ghcr.io/elastic/docs-builder:edge`:

- `.github/workflows/docs-deploy.yml` (Pull and pin docs-builder image)
- `docs-builder/setup/action.yml` (edge branch)

Both already resolve :edge to an immutable RepoDigest. They now also
verify the SLSA build-provenance attestation minted by
docs-builder's prerelease.yml (elastic/docs-eng-team#518), constraining
the attestation issuer to `elastic/docs-builder` via `-R` so an
attacker cannot self-sign under their own repo and have it accepted.

Depends on the producer side shipping in elastic/docs-builder first
and at least one signed :edge push existing in the registry; the verify
call fails closed otherwise.

Co-authored-by: Cursor <cursoragent@cursor.com>
@cotti cotti added the bug Something isn't working label May 16, 2026
cotti and others added 2 commits July 13, 2026 20:43
Add `gh attestation verify` to both consumer paths that pull
`ghcr.io/elastic/docs-builder:edge`:

- `.github/workflows/docs-deploy.yml` (Pull and pin docs-builder image)
- `docs-builder/setup/action.yml` (edge branch)

Both already resolve :edge to an immutable RepoDigest. They now also
verify the SLSA build-provenance attestation minted by
docs-builder's prerelease.yml (elastic/docs-eng-team#518), constraining
the attestation issuer to `elastic/docs-builder` via `-R` so an
attacker cannot self-sign under their own repo and have it accepted.

Depends on the producer side shipping in elastic/docs-builder first
and at least one signed :edge push existing in the registry; the verify
call fails closed otherwise.

Co-authored-by: Cursor <cursoragent@cursor.com>
@cotti
cotti marked this pull request as ready for review July 13, 2026 23:53
@cotti
cotti requested a review from a team as a code owner July 13, 2026 23:53
@cotti
cotti requested a review from reakaleek July 13, 2026 23:53
@reakaleek

reakaleek commented Jul 14, 2026

Copy link
Copy Markdown
Member

This also needs permissions update on every repo that uses this workflow. Otherwise, deploys will start failing.

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

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants