Last week Let's Encrypt published three dates for switching off its OCSP responders, and the reason it gave first was privacy, since every revocation query tells the issuer which site a visitor is on. This is about what a revocation check was ever worth. The answer travels a network path the attacker already controls, and no answer is treated as a good answer.
12 December 2024·6 min read·identitynetworking
The Online Certificate Status Protocol is a small and reasonable idea. A certificate carries the address of a responder run by the authority that issued it; a client that wants to know whether the certificate is still good sends the serial number there and gets back a signed answer saying good, revoked or unknown. It was specified properly and deployed nearly everywhere, and on paper it closes the obvious hole: what to do about a certificate whose private key was stolen before it expires.
Now put the attacker in the picture. The situation revocation exists for is that somebody holds a key they should not, and is using it to sit between a user and a site. That attacker is, by construction, on the network path, and the client's revocation query travels the same path. So the query can be delayed until it times out, dropped, or refused, by the same party whose certificate is the subject of the question.
Every mainstream client responds to that failure by continuing. This is called soft-fail, and it means a network error is treated as a good answer. Adam Langley put it better than anyone has since, writing about Chrome in February 2012: soft-fail revocation checks are like a seat belt that snaps when you crash, and even though it works ninety-nine percent of the time it is worthless, because it only works when you do not need it. Twelve years later that sentence is still the whole subject.
The uncomfortable part is not that the check is imperfect. It is that its failure is correlated with the attack. A control that works except in the presence of an adversary is not a weak control, it is a control whose absence you should be designing around, and most people running one have never checked which of the two they have.
Hard-fail makes the CA an availability dependency. If a client refuses to connect when it cannot reach the responder, then every certificate authority becomes a single point of failure for every site it has ever issued to. A responder outage stops being the authority's problem and becomes an outage of a large slice of the web, in a way no site operator can see coming or route around.
It taxes every handshake. A revocation check is a round trip to a third party before the page starts loading. Mozilla measured the OCSP delay at around 130 milliseconds when it published its own alternative, which is a real cost paid on connections where nothing is wrong, which is all of them. Any control priced per request gets optimized, and the optimization is to stop waiting for it.
The captive portal problem is unanswerable. On a hotel or airport network, everything is blocked until you authenticate through a page that is itself served over HTTPS, whose revocation check cannot complete because you have not authenticated yet. Hard-fail turns that into a device that cannot get online at all. There is no clean fix, because the client genuinely cannot tell a hostile network from an ordinary one that has not let it out yet.
Every OCSP query names a certificate, and a certificate names a site. So the responder learns, as Let's Encrypt put it in July, which website is being visited from that visitor's particular IP address, in real time, as it happens. That is not a bug; it is the protocol working correctly. The infrastructure built to protect users against a stolen key was also, without anybody deciding it should be, a browsing history feed pointed at whoever operates the responder.
OCSP stapling is the honest fix and it is a partial one. The server fetches the signed status for its own certificate on a schedule and staples it into the handshake, which removes the latency and the privacy leak in one move. What it does not remove is the soft-fail: a server that omits the staple looks like one that has not fetched it yet, and the client continues. Must-Staple closes that gap and almost nobody uses it, because a certificate that hard-fails when your own stapling breaks can take your site down.
It is worth being clear about why an authority could not just stop. Running a responder was a root program requirement, so the decision belonged to the browser and operating system vendors rather than to the authority answering the queries. Let's Encrypt's July post notes that the major root programs have made it optional. Permission to switch the thing off arrived from above, years after everyone understood what it was doing.
On 30 January 2025, Must-Staple requests start failing. From that date, a request for a certificate carrying the Must-Staple extension is refused unless the account has issued one before. The population affected is small, which is the point: the feature that would have made stapling enforceable was never adopted widely enough to carry, and step one is closing the door on new users.
On 7 May 2025, the URL leaves the certificate. On that date OCSP URLs are dropped from newly issued certificates, and all Must-Staple requests fail. This is the step that actually changes client behavior, and it changes it silently. A client that would have checked simply finds nothing to check, and the connection succeeds exactly as it did before, which is a fair description of what the check was contributing.
On 6 August 2025, the responders go off. Certificates issued before May carry the old URLs and will outlive the service answering them, so between May and August there is a window in which some clients query a responder that is going away. Publishing all three dates eight months ahead is how that tail avoids becoming somebody's incident.
Instead of the client asking about one certificate at the moment it matters, the client is given the whole answer in advance and consults it locally. Chrome has done a version of this since 2012 with CRLSets, a curated list pushed through the browser's own update channel; Langley's argument was that suppressing a revocation now means blocking the update channel continuously from the moment of revocation, rather than dropping one query at the moment of attack.
Mozilla's CRLite is the more ambitious form of the same shape. Published in 2020, it uses certificate transparency logs and scanning to build a cascade of filters covering revocations across the public web, compressing roughly 300 megabytes of revocation data into about 1 megabyte, updated four times a day. A local lookup replaces a round trip, so the check costs nothing at connection time and tells the authority nothing about who is connecting.
Both approaches move the decision. The authority still revokes, but what your client enforces is curated and distributed by whoever makes your browser, on their schedule, and a revocation that does not make it into the set is not enforced there at all. I think that is the right trade, because a partial answer delivered reliably beats a complete answer delivered over a channel the attacker owns.
Find out which of your controls fail open. The test takes an afternoon: block the dependency and watch what the request does. If the policy service, the token introspection endpoint, the allowlist fetch or the license check times out and the call proceeds, you have a control that is present on the diagram and absent under load. Almost every one I have looked at failed open deliberately, chosen by somebody who was right at the time and did not write it down.
Fail-open is a legitimate choice, undocumented fail-open is not. The decision should be recorded next to the control, with the reason and the conditions, because the person who inherits it will read a green box on a dashboard and believe the check is being enforced. What makes it dangerous is not the behavior but the gap between the behavior and the belief.
Ask whether the failure is correlated with the attack. A control that fails open under random network trouble is a nuisance. A control that fails open specifically when an adversary is present is decorative, because the adversary is the one holding the switch. That question separates the checks that are merely imperfect from the ones that are theater.
Prefer pushed state to queried state on the hot path. Where you can, distribute the answer to the clients ahead of time and let them check locally, the way both browser approaches do. It removes the latency and the disclosure, and it takes the decision away from an attacker who only has to interfere at one moment. The cost is freshness, which is bounded and can be stated, unlike a check that quietly did not run.
I do not want to leave this reading as a claim that revocation is pointless. It works where the party checking is not the party under attack: an authority that revokes a mis-issued certificate creates a record everyone else can act on, and an organization running its own authority and its own clients can enforce hard-fail on both ends because it owns them. The failure described here is the public web, where the client is somebody else's and the network belongs to whoever is closest.
What stays with me is how long a control can sit in a diagram after everyone involved knows what it is worth. Langley published the seat-belt line in 2012 and nothing about the mechanism changed for twelve years, because a check that fails open costs nothing to keep and no incident is ever attributed to it. That is the quiet kind of security debt: not the thing you know is missing, but the thing you know is there.