Skip to content

The embedded Sigstore trusted root has one Rekor log; the live one has two — verification breaks when cosign moves to Rekor v2 #259

Open

Description

@avrabe

Time-sensitive, and it will present as "signatures suddenly stop verifying" rather than as an obvious staleness bug.

The gap

The trusted_root.json embedded in wsc — including on main — is 4,537 bytes and contains one transparency log: rekor.sigstore.dev.

The live Sigstore trusted root contains two: rekor.sigstore.dev and log2025-1.rekor.sigstore.dev, the latter added 2025-09-23 as part of the Rekor v2 / tiled-log migration.

Why it works today and won't tomorrow

RekorKeyring::from_embedded_trust_root() is what the non-bundle verification path uses (signer.rs:629; CertificatePool::from_embedded_trust_root at format.rs:437). Entries written to the v1 log verify, because their logID matches the embedded key.

Checked against a real artifact: varve's v0.28.0 release bundle carries logID c0d23d6a…, which matches the embedded key. So it verifies now.

The moment the cosign version in use starts writing to a log2025-* shard, verify_set fails with "No public key found for log ID", and every newly-created signature becomes unverifiable by wsc's embedded path. Old signatures keep working, which makes it look like a regression in the signing side rather than a stale root.

What survives and what doesn't

  • Bundle path survives — an AirGappedVerifier uses RekorKeyring::from_pem_logs(&self.trust_bundle.transparency_logs), so a bundle built from a current trusted root carries both keys. This is a genuine argument for the bundle design.
  • Embedded path does not. It is pinned to whatever was vendored at build time.

Asks

  1. Refresh the embedded trusted root to include the log2025-* log key. Immediate, mechanical.
  2. Make the staleness visible — a build-time or runtime warning when the embedded root is older than some threshold, or when a logID is unknown, saying "this log is not in the embedded trusted root, which was vendored on " rather than a bare "no public key found". The current message sends the reader to look at the signature, not the root.
  3. Consider making RekorKeyring::from_trusted_root public (rekor_verifier.rs:421) so a consumer can supply a current root without adopting the whole bundle machinery. That is the smallest possible escape hatch for anyone who hits this before a release lands.

Also note trusted_root_to_bundle (tuf.rs:176-199) converts only certificateAuthorities and tlogs — it drops ctlogs (2 present) and timestampAuthorities (1 present) from the real trusted root, so SCT verification is not possible offline from a converted bundle. Separate concern, same function.

Found while evaluating wsc for varve (varve DD-026). Related: sigil#257 (0.11.0 unpublished), sigil#137 (inclusion proofs).

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions