Skip to content

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

Draft
cotti wants to merge 7 commits into
mainfrom
security/verify-edge-attestation
Draft

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

Conversation

@cotti
Copy link
Copy Markdown
Contributor

@cotti cotti commented May 16, 2026

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 signed 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 the 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. Fails closed if the attestation is missing, malformed, or signed by an unexpected workflow.

Commits

  • 0acc418 Verify docs-builder :edge attestation before use

⚠️ Merge ordering

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

  1. elastic/docs-builder#PENDING (security/output-sanitizer) has merged.
  2. 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 behaviour, but it would break deploys repo-wide.

This PR is kept in draft until that prerequisite is met. Convert to ready once a successful signed prerelease run is observable.

Test plan

  • After 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 — should succeed.
  • Open a same-repo docs PR after merge — Pull and pin docs-builder image step shows successful verification before container run.
  • Temporarily point EDGE_IMAGE at a fork-built unsigned image (in a scratch branch) — verify the step fails closed with a clear error.

Made with Cursor

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
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.

1 participant