skip to content

A project's PGP release key was revoked years ago. Why do verifiers still accept its signatures?

level: seniorimportance: nice to knowfreq 30%

answer

  1. publish with no pull on the other end
  2. verification is offline against a local copy
  3. no status responder in the path
  4. pinned pipeline keys never refresh
  5. expiry fails closed, revocation does not

basics

~10 s

OpenPGP revocation is metadata attached to the key, and signature verification is offline against the copy already in the local keyring. Nothing in the verification path fetches revocation status, so nobody sees it.

solid answer

~40 s

Revoking an OpenPGP key means publishing a revocation self-signature, usually by uploading it to a key service. Verification, though, is a local operation against the key copy already imported: there is no status check in the path, no online lookup equivalent to certificate revocation checking, and no expiry on the stale copy. A consumer who imported the key years ago holds a version with no revocation on it and will keep verifying happily. Pipelines are worse — they typically import a pinned key from a file in the repository and never contact a key service at all, and project websites often still list the retired fingerprint. The control that actually fails closed is a short key expiry the maintainer must actively extend, because expiry travels inside the key material every verifier already holds.

go deeper

for a junior

Know that a PGP key can be revoked and that the revocation lives on the key itself. Recall that verification uses whatever copy of the key is on your machine.

for a middle

Explain why the revocation does not reach a verifier: offline verification, stale local keyrings, no status lookup in the path, pinned key files in automation that never refresh.

for a senior

Demonstrate the operating design: short expiry actively extended, keyrings distributed as updatable packages, overlap windows on rolls, and a sequence that never makes disabling verification the fastest fix.

for a principal

Argue the lifecycle policy. Decide who owns upstream key material across the estate, what a supplier's key change obliges contractually, and how you keep an emergency workaround from becoming the permanent configuration.

## How OpenPGP revocation works A key is revoked by generating a **revocation self-signature** — a signature made with the key's own private half (or a revocation certificate produced in advance and stored separately, for the case where the key is lost) — and then attaching it to the public key and publishing it. Any verifier who obtains a copy of the key *carrying that revocation* will report the key as revoked. Everything hard is in the phrase "who obtains a copy carrying that revocation". ## Why the revocation never arrives **Verification is offline by design.** `gpg --verify` recomputes a digest and checks a signature against the key already in the local keyring. There is no network step, no status responder, no revocation list consulted, nothing analogous to the online status checks in the TLS certificate world. Offline verification is a *feature* of this model — it is why air-gapped and long-horizon consumers like it — and revocation propagation is precisely the price. **Local copies go stale silently.** A key imported five years ago is frozen at the moment of import. Refreshing is an explicit, manual act (`gpg --refresh-keys`), it is not scheduled anywhere by default, and on many keys it fails or is slow enough that people stop doing it. **Automation never even looks.** The typical hardened pipeline imports a pinned key from a file in the repository into a scratch keyring, verifies, and exits. That is good practice for pinning — but it means the key material has no path by which a revocation could ever reach it. The pin that protects you from key substitution also freezes you against key retirement. **The publisher's own channels disagree.** The revocation may sit on one key service while the project's website still lists the old fingerprint in its install instructions, and the release announcements from the era the key was live remain online and correct-looking. There is no authority that reconciles them. **Nothing distinguishes a revoked key from a retired one.** Revocation carries an optional reason code, and "key superseded" and "key compromised" mean very different things to a consumer — but a consumer who never fetches the revocation sees neither. ## What a revoked-but-accepted key means for the asset at risk The asset here is mostly **non-repudiation and audit truth**. Old signatures continue to validate, so an artifact signed by whoever holds that retired key remains indistinguishable, to a verifier, from a genuine historical release. If the key was retired *because* it was compromised, the holder can keep minting artifacts that a large tail of consumers accept — and nothing in those consumers' tooling will ever tell them otherwise. It is a control that silently stops being a control. ## What actually works - **Short expiry, actively extended.** Expiry is carried inside the key material that every verifier already holds, so it fails closed with no fetch required. A key valid for a year, extended deliberately each year, converts "nobody sees the revocation" into "everybody sees the expiry". The cost is a recurring maintainer ritual and a support burden when someone forgets. - **Ship the keyring as an updatable package.** Distributions do this: the trusted keys live in a package the normal update mechanism refreshes, so retirement propagates through a channel people already run. If you pin keys in pipelines, give them the same treatment — a reviewed, versioned key bundle that is updated like any other dependency. - **Publish key changes on the release channel.** Announce the new key signed by the old one, publish the revocation and the reason, and update every place the fingerprint appears, including the install docs. Assume some consumers only ever read the release notes. - **Overlap, never cut over.** Sign with both keys for a defined window before retiring the old one, so consumers who lag are not broken by the change itself. ## The operational trap on the other side The mirror image of "nobody sees revocation" is "everybody sees the roll, badly". When a fleet's package repository key is rolled, machines still pinned to the old key start failing to fetch metadata — an availability incident on the whole estate, arriving as a wall of update failures. The path of least resistance for an operator under pressure is to disable signature checking to unblock the fleet, and that switch, once it lands in a configuration-management run, is unlikely to be turned back off. So key lifecycle has to be sequenced deliberately: distribute the new key through the already-trusted keyring first, sign metadata with both keys during an overlap window, verify adoption, and only then retire the old key — so that the correct path is always faster than the workaround. ## The compact answer Revocation in OpenPGP is a *publish* operation with no *pull* on the other end. Design for expiry and for keyring updates that ride a channel consumers already run, and treat revocation as an announcement rather than as an enforcement mechanism.

  • Rolling the key that signs your OS package repository broke fleet updates and operators disabled signature checking to unblock. How should the roll have gone?
    Ship the new key through the existing trusted keyring package first, so every machine has it before it is needed. Sign repository metadata with both old and new keys for an overlap window, watch adoption telemetry, then drop the old signature. The rule is that the correct path must always be faster than the workaround, because a flag that disables verification, once committed to configuration management, effectively never comes back out.
  • Does a revocation reason code change how you respond?
    It should. "Key superseded" or "no longer used" means rotate at your convenience and keep trusting historical releases. "Key compromised" means every artifact signed with it is suspect regardless of date, so you re-verify what you have against the replacement key or re-obtain it. Most consumers never fetch the revocation at all, so in practice the distinction has to be carried by the project's announcement too.
  • Why does pinning a key in CI make this worse rather than better?
    Pinning is the right control against key substitution: the pipeline accepts one fingerprint and nothing else. But a pinned key loaded from a repository file has no path by which a revocation could arrive, so the pin freezes trust indefinitely. Treat the key bundle as a dependency with an owner and a review cadence, not as a constant checked in once.

saying these in an interview costs you the question

  • Assumes gpg checks revocation status during verification
  • Thinks uploading a revocation to a key service is sufficient
  • Believes a revoked key's old signatures stop validating everywhere
  • Cuts over a fleet's repository key with no overlap window
  • Treats disabling signature checks as a temporary measure

context