Revocation Completeness
also called Revocation Assertion, Rotation-Revocation Gap
The verified property that a replaced credential no longer authenticates at the system that accepts it - as distinct from rotation, which only changes what your own services use and leaves the old value working.
A contractor's laptop is found compromised at 11:00. The API key they had access to is rotated in the secrets manager, and by 11:20 the old value appears nowhere in configuration. At 02:40 the next morning, provider audit logs show the old key authenticating successfully from an unfamiliar address.
Rotation is a write; revocation is a delete. A secrets manager stores values, and whether an old value still authenticates is a property of the issuing system - the cloud provider, the partner API, the database. Writing a new version there is one call. Invalidating the old one is a second call, and it is the one routinely skipped, because everything works without it.
Revocation completeness is the practice of asserting the second call happened, rather than inferring it from the first.
Why it matters
The error is invisible by construction. Consumers cache secrets at start-up or for a cache lifetime, so traffic using the old version decays over minutes to hours and then stops - which looks exactly like successful revocation on a dashboard that counts usage rather than validity. And a stolen credential that still works produces no failed authentications, so the usual alert never fires. This is a large part of why credential compromise is measured in weeks of dwell time rather than minutes.
The second reason is that "it appears nowhere in our configuration" is the wrong test, and it feels like the right one. It proves the value is no longer distributed. It says nothing about whether it is still accepted, and the attacker does not need your configuration.
Implementation patterns
- Make expiry do the revoking. Short-lived dynamically issued credentials - a 15-minute database lease, a one-hour cloud role session, a workload identity token - make a stolen value worthless before it is used, with no human step to skip. This is the only fix that holds under pressure.
- End every rotation with a negative test. The final pipeline step authenticates with the old value and must fail. Rotation is not complete until that assertion passes, and the assertion is cheap.
- Alert on authentication by credential version or age, not only on failures. A key older than its rotation interval authenticating at all is an incident; so is version N-1 after the rotation window closes.
- Publish the dwell window. "After rotation the old credential remains valid for up to 60 minutes while consumers converge" should be a decision somebody made, not a side effect of a cache lifetime.
- Maintain a revocation map per credential class: who accepts it, how it is invalidated, and how long invalidation takes to be effective. Build it before an incident, because during one there is no time.
- Shorten consumer caches or support push invalidation, so the convergence window is bounded and known.
- Name the credentials that cannot be revoked - some legacy partner integrations have no mechanism - because those change the response (notify the partner, change the account) rather than the procedure.
Industry example
Cloud providers separate the two operations explicitly in their own documentation: creating a second access key is one API call and deactivating or deleting the first is another, and the published rotation guidance has described a four-step sequence ending in deletion since at least 2015, precisely because the deletion is what gets skipped. compromise consistently show long dwell times between theft and detection, driven by the fact that a valid credential in an attacker's hands generates the same telemetry as legitimate use.
Failure scenarios
- New version created, old never deleted. The case above, found fifteen hours later in provider logs.
- Usage mistaken for validity. Zero traffic on version N-1 is read as revoked when it only means nobody legitimate is using it.
- Partial revocation across replicas. The credential is invalidated in one region or one tenant and remains accepted elsewhere.
- Derived credentials left live. The root key is revoked and the sessions, download URLs or child tokens it minted remain valid for their own lifetimes.
- Cached by a long-lived process. A service holding the secret in memory keeps working, so the rotation looks successful and the operator moves on.
- Revoked, then restored. A deployment pipeline with the old value in a template re-creates it, which is only detectable if something alerts on version age.
Trade-offs
| Choose | Gains | Pays |
|---|---|---|
| Immediate revocation of the old value | Shortest possible exposure | Any consumer that has not converged fails now; an availability event you chose |
| A published convergence window, then revoke | No self-inflicted outage; bounded and known exposure | The attacker has that window, and someone has to actually perform the second step |
| Short-lived credentials everywhere | No rotation procedure to skip | A broker on the critical path for new connections, lease churn, and identities to reap |
In an active compromise the first row is correct and the availability cost is accepted. The mistake is using the second row's leniency outside an incident and never completing it.
When not to use it
For a credential with no revocation mechanism at the issuer, the practice cannot be applied and the honest response is different: treat the value as permanently valid once leaked, and plan for account change or partner notification instead.
For short-lived credentials, revocation is usually not worth building. Expiry already bounds exposure, and adding a revocation list to a one-hour token mostly adds a lookup to every request - the exception is the high-value session where immediate termination is genuinely required.
Interview question
Q: A leaked API key is rotated and the security team confirms the old value is gone from configuration. Two days later the old value is seen authenticating. Walk me through what went wrong, and what you put in place so it cannot recur.
What a strong answer covers: rotation as a write against revocation as a delete, and that only the issuer's state determines validity · why "not in configuration" is the wrong test and why decaying usage looks like success · why no alert fired, since a working stolen credential generates no failures · the negative test as the final rotation step, alerting on credential version and age, and a published convergence window · short-lived credentials as the structural fix, with their honest costs - broker on the critical path, lease churn, identity reaping · derived credentials and multi-region replicas as the partial-revocation traps · and a revocation map per credential class built before the next incident.
Quick check
Quiz: Why does a rotated credential often keep working for hours? Because rotation only changes what your services use; the old value remains accepted until the issuer invalidates it, and cached consumers make the decaying usage look like successful revocation.
Flashcard: What is the final step of a complete rotation? - An authentication attempt with the old value that must fail; until that assertion passes, the credential has been replaced but not revoked.