35,000 of 4 Million: CRLSets, Bloom Filters and the Revocation Gap
Chrome's CRLSet covers roughly 1% of revoked certificates. Here is why, how Bloom filters (and their successors) let Firefox cover all of them, and why short-lived certificates change the question.
A certificate is a promise that lasts until its expiry date. Sometimes you need to break that promise early: the private key leaked, the CA issued it by mistake, the domain changed hands. The mechanism for that is revocation, and it is the part of the web PKI that works the least well. This article explains why browsers stopped asking CAs about revocation in real time, what Chrome's CRLSets do in its place, and how the small internal CA I run at home sidesteps the whole problem.
The two original answers, and why they failed
The standard defines two ways to find out whether a certificate is revoked. A CRL (certificate revocation list) is a file published by the CA listing the serial numbers of revoked certificates. It is simple, but it grows with every revocation and the client has to download all of it. OCSP (Online Certificate Status Protocol) lets the client ask the CA about a single certificate, which is lighter, but it has costs of its own:
- Latency. A blocking request to a third party before the page can load.
- Privacy. The CA learns which sites you visit, since you ask about each certificate.
- Availability. If the responder is down, what does the browser do?
That last question is the one that broke it. Browsers chose soft-fail: if the revocation server does not answer, assume the certificate is fine, because otherwise a CA outage would take half the web down. But an attacker who can intercept your traffic well enough to use a stolen key can also drop the OCSP request. Soft-fail therefore protects against nothing in exactly the situation where you need it. Revocation checking that an attacker can switch off by blocking a request is, as security people say, a speed bump.
CRLSets: a curated list pushed to the browser
Chrome's answer is the CRLSet. Instead of asking a CA at connection time, Chrome receives a small list of revoked certificates through its own update channel, in the background, like any other component. The list is compact and chosen by Google: it is built from the CRLs that CAs publish, but it is deliberately not complete. Chromium's documentation states a size limit of 250 KB, and it describes how entries are picked: only revocations with no reason code, or with a reason such as key compromise or CA compromise, are included, and CRLs covering intermediates and EV certificates are taken in preference.
How much does that fit? Mozilla, which has every reason to measure it, reports in its 2025 post on CRLite that Chrome's CRLSet is about 600 kB a day and holds roughly 35,000 revocations. The web has about 4 million revoked certificates at any time. That is around 1%. (Those figures come from a competitor and describe 2025; Chromium's own page does not state an entry count, and its 250 KB limit differs from the size Mozilla observed, so treat both as orders of magnitude.)
The consequences are worth spelling out:
- No connection-time cost. The check is a local lookup against data already on your machine. No latency, nothing leaked to a CA.
- No soft-fail loophole. There is no server to block. The list is there or it is not.
- But it is partial. A revoked ordinary site certificate may simply not be in the list. CRLSets are a fast emergency brake, not a full revocation database.
- The freshness depends on updates. A browser that is offline or not updating components has an old list.
The size problem has a history: mass revocations, the best-known being the aftermath of the Heartbleed bug in 2014, produced far more revoked certificates than a list this small can carry. That event is much of why people stopped believing in revocation as a safety net.
Fitting 4 million revocations in a few hundred kilobytes
Mozilla attacked the completeness problem instead. CRLite encodes all revocations, not a selection, and ships them to Firefox. According to Mozilla, that is about 300 kB of data per day plus a snapshot of roughly 4 MB every 45 days, against about 300 MB for the raw CRLs. It is enabled for desktop Firefox since version 137. The trick is a probabilistic data structure.
A Bloom filter answers "is this item in the set?" using a few bits per item. It can say "definitely not" or "probably yes". It never forgets an item it holds (no false negatives), but it sometimes claims to contain one it does not (false positives). For revocation that is the wrong way round if you use it naively: a false positive would mean wrongly rejecting a perfectly valid certificate.
CRLite's original design fixed this with a cascade. The first filter holds the revoked certificates. Every valid certificate that wrongly matches it, which Mozilla can enumerate because it knows the whole set of publicly logged certificates, goes into a second filter. The few revoked certificates that falsely match that one go into a third, and so on until nothing is left. Walk the levels and you get an exact answer for every certificate that was known when the cascade was built. The current implementation replaces the stack of Bloom filters with a two-level cascade of more compact Ribbon filters (the "Clubcards" design), which is why the numbers above are so small.
The trade-off is the mirror image of Chrome's: complete coverage and exactness, but only for certificates that appear in Certificate Transparency logs, and only as fresh as the pipeline that rebuilds it.
OCSP stapling and the "Must-Staple" extension are a third path: the server fetches a signed OCSP response itself and presents it during the handshake, so the browser does not have to contact the CA. It fixes latency and privacy, but not the soft-fail problem unless the certificate says the staple is mandatory, and few sites ask for that.
The industry's real fix: make certificates expire sooner
If revocation is unreliable, the other lever is lifetime. A certificate that expires in a week needs no revocation: by the time you notice a problem, it is already nearly gone. The CA/Browser Forum has been moving in this direction. Maximum validity dropped to 398 days years ago, and a 2025 ballot schedules a staged reduction, with a ceiling of 200 days that is already in force and further cuts planned in the following years. Automation (ACME) is what makes it possible: nobody renews 47-day certificates by hand. Some CAs now offer certificates that live for only a few days. Responders have followed: the CA/B Forum made OCSP optional and CRLs mandatory for public CAs, and Let's Encrypt has dropped OCSP in favour of CRLs.
What this means for a homelab PKI
My internal CA is a step-ca instance: an offline root key, an intermediate on the server, ACME to issue certificates to Caddy. I did not build any revocation infrastructure, and I do not intend to, for three reasons:
- Certificates last 24 hours (the policy caps them at seven days). A key stolen today stops working tomorrow, with no list to distribute and nothing for a client to check.
- The root has name constraints. It can only sign names under my private domain, so even a stolen intermediate cannot be used to impersonate a public site to a machine that trusts my root. That limits the damage in a way no revocation list could, because it is enforced by the client during path validation.
- The root key is offline. The thing worth revoking, the root, is the thing least likely to leak.
It also matches how browsers treat private roots: the curated, centrally updated revocation data they ship is built for public CAs, so a certificate chaining to a root you installed yourself should not be expected to benefit from it. For a private PKI, short lifetimes are not just a convenience, they are the revocation strategy.
Takeaways
- Online revocation checking was abandoned because soft-fail makes it useless against an active attacker.
- CRLSets give Chrome a fast, private, local emergency list, at the cost of completeness.
- CRLite aims at completeness with a cascade of probabilistic filters (Bloom, now Ribbon); stapling shifts the work to the server.
- The robust answer is shorter certificate lifetimes plus automation.
- In a private PKI, combine short lifetimes, name constraints and an offline root, and revocation mostly stops being your problem.