SBOM & Compliance

Sigstore Rekor Transparency Log Operations

Rekor is the transparency log behind Sigstore, and understanding its operational model matters more than most teams realise. Here is how we run against it in production.

Nayan Dey
Senior Security Engineer
7 min read

Rekor is the quiet component of Sigstore. Fulcio gets attention because short-lived certificates are a visibly new idea. Cosign gets attention because it is the CLI most engineers interact with. Rekor gets less attention because it looks, at first glance, like "a log." But the log is where the security properties actually come from. Without Rekor, a Fulcio certificate that was valid for ten minutes in the past is indistinguishable from a forged certificate, and cosign's verification claims rest on a foundation that has no anchor.

This post is a tour of Rekor as an operational system. It covers what Rekor actually stores, how inclusion proofs work, what checkpoints are for, and the differences between the public good instance at rekor.sigstore.dev and private deployments. It is based on running against the public instance since 2022 and operating a private deployment for a regulated customer since late 2023.

What does Rekor actually store?

Rekor, as of v1.3 (released in October 2023), stores entries in a Merkle tree backed by Trillian. Each entry is a signed record of a "thing that happened," where "thing" is one of several supported types. The most common types are hashedrekord (a signature over a digest), dsse (a DSSE envelope), and intoto (a legacy in-toto v0.1 envelope). There is also cosign for container image signatures and rekord for a generic signed blob, though these are less common in modern pipelines.

An entry is not the signed object itself. It is a small record referencing the signed object by hash, together with the public key or certificate that produced the signature. Rekor does not store the DSSE payload directly; it stores the envelope's signature, the payload digest, and the signing material. That distinction matters for storage planning: Rekor is sized for high entry count, not for large payload retention.

When cosign signs an artifact using keyless mode, three things end up in Rekor's tree. The entry type (typically hashedrekord for container images), the Fulcio certificate that was used, and the signature bytes. The Rekor response to cosign includes a log index, a log ID, an integrated time, and an inclusion proof. All four matter for later verification.

How do inclusion proofs and checkpoints work?

An inclusion proof is a Merkle tree path showing that a given entry is part of the current tree root. When cosign publishes an entry, Rekor returns an inclusion proof relative to the current tree state. The proof is a list of sibling hashes and a tree size, which a verifier can walk back to a root hash.

The root hash is only meaningful if you can compare it to a trusted reference. That reference is the Rekor checkpoint: a signed statement from Rekor saying "at tree size N, the root hash is H." Checkpoints are produced periodically and signed by a Rekor instance key. A verifier consistent with the client-spec from sigstore/rekor (v1.3+) should fetch a recent checkpoint, verify the checkpoint signature against the Rekor public key, confirm that the inclusion proof's tree size is at most the checkpoint's tree size, and then walk the proof to get the root hash.

The subtle failure mode here is that cosign versions before v2.0 did not always verify checkpoints correctly. Some early versions verified the inclusion proof against a tree state provided by Rekor itself, which is circular: Rekor could lie about both the proof and the tree state and a verifier would not notice. cosign v2.0+ fixed this by verifying checkpoints against trusted root material from The Update Framework (TUF) repository at tuf-repo-cdn.sigstore.dev.

What is the offline verification story?

A recurring question from compliance teams is whether you can verify Sigstore signatures offline. The answer is "yes, but you need to plan for it." Offline verification requires three things: the signed artifact with its attached signature, the Fulcio certificate used to sign, and a Rekor transparency log entry with an inclusion proof bundled in.

cosign v2.2 introduced the --rekor-url flag behavior that embeds a Rekor bundle into the OCI signature annotations. The bundle contains the signed entry timestamp (SET), the log index, the log ID, and the inclusion proof. A verifier that has the bundle, the Fulcio certificate, the Rekor public key (from TUF), and the Fulcio root certificate can confirm the signature without reaching out to any network endpoint.

We run offline verification for the air-gapped deployment we manage, and the constraint that keeps biting us is TUF refresh. The Sigstore TUF root rotates periodically, and an air-gapped verifier that has not refreshed its TUF metadata in six months will fail to verify new signatures. We run a small sync process that refreshes the TUF repository into an internal mirror on a weekly cadence.

When should you run a private Rekor?

The public Rekor instance at rekor.sigstore.dev is free to use and has been stable since general availability in 2022. For most teams, it is the right default. The reasons to run a private Rekor deployment fall into three categories.

First, data residency. Some regulated deployments cannot have their hash records leave a specific jurisdiction. A private Rekor instance inside that jurisdiction solves this. Second, rate limits. The public instance is rate-limited, and very high-volume build pipelines (more than a few thousand signatures per hour from a single network) can hit limits. Third, policy isolation. A private Rekor combined with private Fulcio lets you tie acceptance policy to certificate identities that are meaningful only in your organisation.

Running private Rekor is non-trivial. The upstream Helm chart at sigstore/helm-charts is the starting point, and it pulls in Trillian, a MySQL database, and the Rekor server. You need to operate the MySQL carefully because Trillian's write path is append-only but the database still needs capacity planning. The instance key is what identifies your Rekor to consumers; if it rotates or leaks, every consumer needs to update their trust root.

What do verifiers need to check?

A complete Rekor verification does four things. It checks the Fulcio certificate's validity period, binding the signing identity to the claimed OIDC subject. It checks the signature over the artifact (or the DSSE envelope payload for attestations). It checks the Rekor inclusion proof against a recent checkpoint. And it checks that the entry's integrated time falls within the certificate's validity period; this is the step that catches certificates used after expiry.

The integrated time check is easy to get wrong. Rekor's integratedTime is a Unix timestamp in seconds, and the Fulcio certificate's notBefore and notAfter are RFC 5280 times with optional milliseconds. A naive comparison that does not normalise timezones or precision can fail in edge cases. The Sigstore policy verifier library (sigstore-python v3.0, sigstore-java v1.1) handles this correctly; most homegrown verifiers we audit do not.

How Safeguard Helps

Safeguard verifies Rekor entries as part of every artifact ingestion, checking the inclusion proof against fresh TUF-anchored checkpoints, validating the Fulcio certificate chain, and confirming integrated time against the certificate validity window. Customers running private Rekor instances configure the trust root once and Safeguard routes verification to their deployment automatically. We surface any entry where cosign verification succeeded but the Rekor bundle was incomplete or missing, which is a common failure mode in pipelines using older cosign versions. For regulated deployments we maintain an offline TUF mirror so verification continues even when upstream Sigstore is unreachable.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.