Manav.id
Comparison · 4 min read

Revocation without a network call at verification time

Revocation without a network call at verification time

The certificate ecosystem spent two decades learning that asking a server whether something is revoked, at the moment you need to know, is a bad design. That lesson transfers directly.

Why does online revocation checking fail open?

Because an unreachable responder cannot be allowed to block all verification. The certificate ecosystem learned this over two decades: a check that is skipped when the responder is unavailable is a check an attacker can disable by making the responder unavailable.

Key takeaways
  • Online status checks leak the subject being verified to the responder and add latency to every verification.
  • Because an unreachable responder cannot be allowed to block everything, implementations fail open — which makes the check optional in practice.
  • A signed list distributed ahead of time is checkable offline, leaks nothing, and fails closed on the entries it covers.

The three problems with asking

Online status checkLeaks the subject to the responderRound trip on the critical pathFails open when unreachableUsually cached for hours anywaySigned listLeaks nothingNo call at verificationCached list still enforcedFresh to the publication intervalvs
ProblemDetail
PrivacyThe responder learns which subject you are verifying, when, and from where
LatencyA network round trip on the verification path, at the worst possible moment
AvailabilityAn unreachable responder blocks verification, so implementations fail open

The third is the one that matters most. A check that is skipped when the responder is unavailable is a check an attacker can disable by making the responder unavailable.

What a signed list does instead

Publish the revoked set, signed, on a schedule. Verifiers fetch it periodically and check locally.

{
  "issued": "2026-03-09T12:00:00Z",
  "next_update": "2026-03-09T12:05:00Z",
  "revoked_keys": [
    { "kid": "2025-11-c", "effective": "2026-02-14T08:22:00Z",
      "reason": "key_compromise" }
  ],
  "revoked_nonces": [
    "n_88213aa1", "n_4471bf02", "n_9c1f8a3e"
  ],
  "signature": "..."
}

Two categories, and both matter. Revoking a key invalidates a class of signatures from a point in time. Revoking a nonce invalidates one specific authorisation — which is what you need when an individual approval was obtained fraudulently.

The staleness objection, addressed

A list is as fresh as its publication interval. The usual complaint is that this is worse than asking in real time.

In practice online responses are also cached, often for hours, so the freshness advantage is smaller than it appears. And the interval is a choice: a list published every minute is a minute stale, which for revocation of a specific authorisation is entirely adequate.

IntervalSuitable for
Every few secondsHalting an in-flight automated process
Every minuteRevoking a specific authorisation
Every hourKey revocation, which is rare
DailyNot adequate for anything that matters

Keeping the list small

The obvious concern with a full list is that it grows without bound. Three techniques keep it bounded.

  1. Expire entries. A nonce for a statement that has expired can leave the list — the statement is unusable anyway.
  2. Use effective times for keys. One entry with a timestamp covers every signature from that key after that moment, rather than listing signatures.
  3. Partition by scope. A verifier for one service does not need revocations for another, so publish per-scope lists.

With those, the steady-state list for a typical deployment is small enough to fetch frequently without concern.

The stapling middle ground

A third option worth knowing: the party presenting the receipt includes a recent signed status assertion alongside it.

This removes the verifier's network call and the privacy leak, and shifts the freshness burden to the presenter. It is a good fit where receipts are presented rather than looked up, and it adds a moving part.

Comparing honestly

PropertyOnline status checkSigned listStapled assertion
Verifier network callYesOnly to refreshNo
Privacy leak to responderYesNoNo
FreshnessReal time, if uncachedPublication intervalAs stapled
Behaviour when unreachableFails open in practiceCached list still worksPresenter cannot staple
Implementation complexityLowLowModerate

The signed list wins on the properties that determine whether the control actually operates, and gives up real-time freshness that online checks mostly do not deliver either.

Where to check

At the point of effect, not at a gateway. A revocation checked at an API gateway does not stop work already past the gateway: queued jobs, retries, in-flight requests.

And fail closed on unknown. If a receipt references a key id that is not in your cached key set, that is not an unknown-but-probably-fine situation; it is a refusal.

Two kinds of revocation, both needed

What each entry invalidates
EntryScope
Revoked key, with an effective timeEvery signature from that key after that moment
Revoked nonceOne specific authorisation

The second is what you need when an individual approval was obtained fraudulently and the credential itself is fine. Key-level revocation is too blunt for that case and is what most systems offer.

Objections and honest limits

“A list is staler than a real-time check.” Online responses are typically cached for hours, so the freshness advantage is smaller than it appears. A list published every minute is frequently fresher than what the callback actually delivers.

“The list will grow without bound.” Expire entries whose statements have expired, use effective times for keys rather than listing signatures, and partition by scope. Steady-state size is small.

Implementing revocation well

  1. Publish a signed, cacheable list. Per scope, on a short interval.
  2. Support both key and nonce revocation. Blunt and precise.
  3. Check at the point of effect. A gateway check misses queued work and retries.
  4. Fail closed on unknown key ids. An unrecognised key is a refusal, not a maybe.

Terms used here

Soft-fail
Proceeding when a revocation check cannot be completed — the near-universal behaviour, and the reason the check is optional in practice.
Effective time
The moment from which a key revocation applies, so earlier signatures remain valid.
Stapling
The presenter attaching a recent signed status assertion, removing the verifier's network call.

Frequently asked questions

Why do online status checks fail open? Because an unreachable responder would otherwise block all verification. That makes the check optional whenever the responder can be made unavailable.

Isn't a list staler than a real-time check? Online responses are typically cached for hours anyway. A list published every minute is adequate for revoking a specific authorisation.

How do you keep the list small? Expire entries for statements that have expired, use effective timestamps for keys rather than listing signatures, and partition by scope.

Where should the check happen? At the point of effect. A gateway check misses queued work, retries and in-flight requests already past it.

Why do online checks fail open? Because blocking all verification when a responder is down is unacceptable, which makes the check optional whenever the responder can be made unavailable.

Is a published list too stale? Online responses are cached for hours anyway. A list published every minute is adequate for revoking a specific authorisation.

Why revoke a nonce rather than a key? Because when one approval was obtained fraudulently the credential is fine. Key revocation is too blunt for that case.

Where this fits in Manav

Manav's receipt is deliberately small: RFC 8785 canonicalisation, one signature algorithm, keys published at a well-known URL, and a verifier short enough to audit or reimplement.

Read the architecture →

Sources and further reading