SECOND MEASUREMENT SM-009
Firefox promised a list of every revoked certificate. A third of the ones revoked on day one aren’t on it, and it no longer asks anyone else
Since August 2025, Firefox decides whether a website’s certificate has been revoked by looking it up in a list it downloads twice a day, called CRLite, instead of asking the certificate authority. Mozilla says the list holds all revocations, and Firefox skips the online check for anything the list doesn’t cover. We pulled 1,718 fresh revocations straight from 125 certificate authorities’ own revocation lists and asked today’s Firefox filters about each one, using Mozilla’s own query code. Of the 465 we could test exactly, 427 come back revoked and 38 come back good or not covered (36 and 2). Among certificates revoked within a day of being issued, 37 of 108 pass. Every one of the 38 carries timestamps only from logs with a 24-hour merge delay, a gap Mozilla wrote up a year ago and hasn’t closed. They stay invisible until the next full filter, and the current one is dated 2 September.
- Mozilla, August 2025: CRLite “is efficient enough to store all certificate revocations locally”. Firefox 142 and later enforce it and, for ordinary certificates the list doesn’t cover, skip the online check.
- We took 1,718 revocations from the CAs’ own lists, 2 to 30 days old, across 125 organisations, and queried Firefox’s current filters.
- Of the 465 with the exact data Firefox would see: 427 revoked, 38 good or not covered. Revoked within 24 hours of issuance: 37 of 108 pass. Revoked later: 1 of 357.
- All 38 were logged only to 24-hour merge-delay logs, the mechanism in Mozilla’s own issue 367. The fix merged in September 2025; the gap is still there.
- They stay “good” until the next full filter. The current one is 30 days old; the oldest invisible revocation in our sample is 28 days old.
- None of the 32 key-compromise revocations in the sample was missed. The 38 are mostly reissues: reason “superseded” or none given.
Disclosure: Markovian Protocol holds no financial position in any organisation named here, was paid by no one for this work, and showed it to no one before publication except the organisation measured. How we work.
A certificate authority publishes a certificate revocation list, a CRL: the serial numbers of certificates it has cancelled before they expire. CRLite is Mozilla’s way of shipping every such list to every Firefox at once. Mozilla’s servers read the CRLs of every CA Firefox trusts, compress the result into a filter about 6 MB in size, and push small updates twice a day. Firefox 142 made its answers final. The filter can only answer for certificates it knows about, and it knows a certificate through the timestamps the certificate carries from Certificate Transparency logs. When those timestamps say the filter can’t know yet, Firefox treats the certificate as not covered. For an ordinary domain-validated certificate chaining to a built-in root, Firefox then skips the online OCSP check and lets the connection through. Mozilla’s source comments say so in as many words.
What they said, what we found
| Mozilla said | We found |
|---|---|
| “CRLite is efficient enough to store all certificate revocations locally, requiring only 300KB per day of continuous updates to stay current.” (Firefox blog, 19 August 2025)1 | Of 465 current revocations tested with the exact certificate: 427 stored, 38 not. Revoked within 24 hours of issuance: 37 of 108 not stored, after 4 to 28 days. |
| The same sentence: “requiring only 300KB per day of continuous updates to stay current.”1 | Desktop channel, last 30 days: 61 deltas, 13.46 MB, 441 KB a day; 649 KB a day counting the 6.3 MB snapshot. Android channel: 238 KB a day. From the Remote Settings records in the exhibits. |
| Firefox’s verifier: when the filter doesn’t cover a certificate, “it’s reasonable to skip the synchronous OCSP request here. In effect, we’re choosing to preserve the privacy of the user at the risk of potentially allowing them to navigate to a site that is serving a revoked certificate.”2 | True to the code. The 38 certificates come back “Good” (36) or “NotCovered” (2); either way the connection proceeds. |
| Firefox on Android subscribes to a smaller “compat” channel that carries only three revocation reasons: key compromise, cessation of operation, privilege withdrawn.3 | On that channel 419 of the 465 revoked certificates come back good. That is by design, and it isn’t what the blog post says. |
How Firefox decides
Picture a doorman with a printed guest list who used to phone the office for anyone he wasn’t sure about. Now he carries the list and has stopped phoning. The list is reprinted twice a day. The catch is how a name gets on it.
Every public certificate is logged to Certificate Transparency before it’s used, and carries two or three signed timestamps from those logs. Each log promises to publish an entry within its merge delay: 24 hours for the older logs, 60 seconds for the newer tiled ones. Mozilla’s filter says, for each log, “I have seen everything in this log up to time T”, and T is one merge delay behind what the server has actually read. Firefox checks a certificate’s timestamps against those T values. If none of the certificate’s logs has reached it yet, the filter is not consulted, and nothing else is either.
Mozilla’s John Schanck described the failure in September 2025, in the project’s issue tracker.4 A certificate that is revoked within one merge delay of being logged lands in the revoked set while the filters still count it as unknown. The twice-daily updates only carry what is newly revoked, so once the certificate is in the set, no later update mentions it again. The next full filter would include it. The current full filter is dated 2 September. Everything since has been an update.
We timed that promise ourselves. A fresh certificate submitted to every log on the Google and Apple lists that will take one today, 64 logs, was served by all of them inside their stated delay: the 43 tiled logs within 6 seconds, DigiCert’s classic logs in 10, Google’s and Sectigo’s in one to two minutes, TrustAsia’s in two and a half, and Cloudflare’s Nimbus in 46 and 61 minutes. The 24-hour figure the filter waits on is a ceiling; the logs run between twenty-four and a thousand times under it. The gap is in what the client assumes, not in what the logs do (the check).
A fix merged on 25 September 2025.5 In November a user reported Let’s Encrypt’s own revoked test site still showing as good; Schanck explained that the certificate’s embedded timestamps came from two 24-hour logs and that the problem “will more or less resolve itself once CAs start logging precertificates to static CT logs”.6 Our sample says most CAs haven’t yet: all 38 certificates that slipped through were logged only to 24-hour logs.
The count
We did not use Mozilla’s data. The revocations come from the CAs: CCADB, the shared database of browser root programs, lists 18,328 CRL files for the intermediates Firefox trusts. We fetched 2,201 of them at random and parsed 2,198 (12 per organisation, 150 extra for organisations with hundreds of shards), parsed 173,408 revocations dated between 2 and 30 days ago, and drew up to 20 per organisation: 1,718 from 125 organisations. crt.sh, the public Certificate Transparency search engine, found 1,108 of them; the rest are mostly not website certificates at all, since CAs put client and email certificates on the same CRLs. 41 had expired. That left 1,067 to query.
Firefox judges a certificate by its issuer’s key, its serial number, and its embedded log timestamps. For 465 of the 1,067, crt.sh holds the final certificate, so all three are exact and we ran Mozilla’s own rust-query-crlite on the file. For the other 602, only the precertificate is public, and the timestamps come from crt.sh’s record of which logs it saw the precertificate in. That record is incomplete for several logs, so those 602 are reported separately and left out of the headline.
| Firefox desktop filter, 2 October | Revoked | Good | Not covered | Slips through |
|---|---|---|---|---|
| 465 with the final certificate (exact) | 427 | 36 | 2 | 38 (8.2%) |
| of which revoked within 24 h of issuance | 71 | 35 | 2 | 37 of 108 |
| of which revoked later than 24 h | 356 | 1 | 0 | 1 of 357 |
| 602 with only the precertificate (crt.sh timestamps) | 563 | 5 | 34 | see note |
Filters downloaded 2 October 2026 with rust-query-crlite --update prod: snapshot 20260902-0 plus 61 deltas, newest effective 13:01 UTC. “Not covered” in the precertificate rows is mostly crt.sh missing the certificate’s other logs, not Firefox; see what we can’t be sure of.
Firefox’s own query tool agrees with our raw-key path on 463 of 465 exact cases. The two “expired” disagreements are certificates that expired during the day of the run.
The 38 that slip through:
| Issuer | Issued (UTC) | Revoked by CA | Hours between | Reason on CRL | Firefox says |
|---|---|---|---|---|---|
| Hellenic Academic and Research Institutions CA | 2026-09-04 08:59 | 2026-09-04 09:09 | 0.2 | none given | Good |
| UniTrust | 2026-09-07 03:39 | 2026-09-07 13:50 | 10.2 | none given | Good |
| UniTrust | 2026-09-08 09:34 | 2026-09-08 09:42 | 0.1 | none given | Good |
| DNSPod, Inc. | 2026-09-09 08:42 | 2026-09-09 10:01 | 1.3 | none given | Good |
| Hellenic Academic and Research Institutions CA | 2026-09-09 09:56 | 2026-09-09 10:17 | 0.4 | affiliation_changed | Good |
| SSL Corp | 2026-09-10 16:02 | 2026-09-10 19:46 | 3.7 | superseded | Good |
| SSL Corp | 2026-09-10 16:05 | 2026-09-10 19:35 | 3.5 | superseded | Good |
| SSL Corp | 2026-09-10 16:06 | 2026-09-10 19:15 | 3.2 | superseded | Good |
| SSL Corp | 2026-09-10 16:09 | 2026-09-10 19:26 | 3.3 | superseded | Good |
| SSL Corp | 2026-09-10 16:12 | 2026-09-10 19:12 | 3.0 | superseded | Good |
| Cybertrust Japan Co., Ltd. | 2026-09-11 01:37 | 2026-09-11 03:44 | 2.1 | superseded | Good |
| UniTrust | 2026-09-11 08:41 | 2026-09-11 13:45 | 5.1 | none given | Good |
| SSL Corp | 2026-09-11 15:11 | 2026-09-11 20:18 | 5.1 | none given | Good |
| SSL Corp | 2026-09-11 15:11 | 2026-09-11 20:17 | 5.1 | none given | Good |
| PKI(Chongqing) Limited | 2026-09-12 13:33 | 2026-09-12 18:55 | 5.4 | none given | Good |
| PKI(Chongqing) Limited | 2026-09-12 13:54 | 2026-09-12 19:20 | 5.4 | none given | Good |
| PKI(Chongqing) Limited | 2026-09-12 14:17 | 2026-09-12 19:20 | 5.0 | none given | Good |
| UniTrust | 2026-09-13 01:25 | 2026-09-13 03:30 | 2.1 | none given | Good |
| Shanghai Huandu Info Tech Co. Ltd. | 2026-09-14 03:12 | 2026-09-14 08:30 | 5.3 | none given | Good |
| UniTrust | 2026-09-14 07:00 | 2026-09-14 09:15 | 2.2 | none given | Good |
| NAVER Cloud Trust Services Corp. | 2026-09-17 00:00 | 2026-09-17 11:34 | 11.6 | affiliation_changed | Good |
| Actalis S.p.A. | 2026-09-17 07:10 | 2026-09-18 12:55 | 29.7 | none given | Good |
| Hellenic Academic and Research Institutions CA | 2026-09-17 08:05 | 2026-09-17 08:16 | 0.2 | none given | Good |
| Google Trust Services | 2026-09-19 02:36 | 2026-09-19 08:22 | 5.8 | cessation_of_operation | NotCovered |
| UniTrust | 2026-09-20 00:50 | 2026-09-20 03:10 | 2.3 | none given | Good |
| Shanghai Huandu Info Tech Co. Ltd. | 2026-09-21 02:13 | 2026-09-21 02:43 | 0.5 | none given | Good |
| NETLOCK Kft. | 2026-09-21 08:25 | 2026-09-21 08:31 | 0.1 | superseded | Good |
| DigiCert, Inc | 2026-09-22 00:00 | 2026-09-22 09:04 | 9.1 | superseded | Good |
| DigiCert, Inc | 2026-09-22 00:00 | 2026-09-22 09:04 | 9.1 | superseded | Good |
| DigiCert, Inc. | 2026-09-22 00:00 | 2026-09-22 09:04 | 9.1 | superseded | NotCovered |
| UniTrust | 2026-09-22 02:36 | 2026-09-22 03:55 | 1.3 | none given | Good |
| UniTrust | 2026-09-22 16:36 | 2026-09-22 16:40 | 0.1 | none given | Good |
| UniTrust | 2026-09-22 16:38 | 2026-09-22 16:40 | 0.0 | none given | Good |
| Gandi SAS | 2026-09-23 00:00 | 2026-09-23 10:13 | 10.2 | none given | Good |
| Henan Fierce Fire Network Technology Co., Ltd. | 2026-09-25 01:27 | 2026-09-25 02:13 | 0.8 | none given | Good |
| Shanghai Huandu Info Tech Co. Ltd. | 2026-09-28 02:20 | 2026-09-28 09:05 | 6.7 | none given | Good |
| GeoSSL, Inc. | 2026-09-28 08:10 | 2026-09-28 08:24 | 0.2 | none given | Good |
| Henan Fierce Fire Network Technology Co., Ltd. | 2026-09-28 10:42 | 2026-09-28 11:19 | 0.6 | none given | Good |
All 38 carry timestamps only from logs with a 24-hour merge delay (Argon, Xenon, Tiger, Elephant, Sphinx, Wyvern, Nimbus, HETU, TrustAsia log2026a). None of the 11 key-compromise revocations in the 465 was missed; none of the 21 in the other 602 either.
How this ends
It ends when Firefox’s filter stops waiting a full merge delay on the classic logs, or when the certificates that matter are logged somewhere it reads promptly. The daily recheck re-asks each day’s filter about the same revoked certificates; the number still coming back “good” is the ending, counted down.
The evidence
Every quote below was copied from the source and checked against a saved copy, fetched 2026-10-02. The copies, the certificates, the two filter files, and their SHA-256 hashes are published next to this page (SHA256SUMS).
Exhibit 1 · The claim, 19 August 2025
“Other browsers have deployed similar approaches, but these systems have only been able to store a small fraction of all revoked certificates, necessitating imperfect guesswork as to which ones are most important. CRLite is efficient enough to store all certificate revocations locally, requiring only 300KB per day of continuous updates to stay current.”
blog.mozilla.org/en/firefox/crlite/ · saved copy exhibit_mozilla_blog_crlite.html
Exhibit 2 · What Firefox does when the list can’t answer
// There are a few situations where the user's CRLite data may not cover a
// certificate that chains to our root store, e.g.
// 1) the user has not yet downloaded CRLite filters, or
// 2) the user's CRLite filters are out-of-date, or
// 3) the certificate has been in CT for < 1 MMD interval.
// If we're configured to enforce CRLite and we're configured to tolerate OCSP
// soft failures, then it's reasonable to skip the synchronous OCSP request
// here. In effect, we're choosing to preserve the privacy of the user at the
// risk of potentially allowing them to navigate to a site that is serving a
// revoked certificate.
if (mOCSPFetching == RevocationCheckMayFetch &&
mCRLiteMode == CRLiteMode::Enforce && mIsBuiltChainRootBuiltInRoot) {
return Success;
}security/certverifier/NSSCertDBTrustDomain.cpp, Firefox main branch · saved copy NSSCertDBTrustDomain.cpp · defaults: security.pki.crlite_mode = 2 (enforce), security.pki.crlite_channel = “default” on desktop, “compat” on Android (StaticPrefList-crlite.yaml)
Exhibit 3 · A certificate revoked two minutes after issuance, still good ten days later
CRL: http://crl.global.sheca.com/govtlscav2a1.crl (UniTrust, thisUpdate 2026-10-02 09:02 UTC) serial 11a620cae4d9e34c80122a2affe1bc04 revoked 2026-09-22 16:40:41 UTC certificate notBefore 2026-09-22 16:38:14 UTC, logs: Xenon2027h1, Argon2027h1, Tiger2027h1 $ rust-query-crlite -d db_default -vvv x509 example-revoked-still-good.der TRACE - 20260902-0-default.filter: NotCovered ... every delta through 20260923-1: NotCovered ... TRACE - 20260924-0-default.filter.delta: Good ... every later delta: Good ... INFO - example-revoked-still-good.der Good
certificate example-revoked-still-good.der · the CA’s CRL example-crl.der and its entry example-crl-entry.txt · full trace example-query-default.log
Exhibit 4 · Mozilla’s own description of the gap, 16 September 2025
“Certificates that are revoked within the merge delay of the log in which they were discovered may not be marked as revoked until the next full snapshot filter is published. … But in our current configuration this could be up to 45 days after issuance.”
mozilla/crlite issue 367, opened by jschanck · saved crlite-issue-367.json
Exhibit 5 · The same gap after the fix, 13 November 2025
“Unfortunately, clients decide which clubcards to query based on the SCTs that a certificate is presented with. And the embedded SCTs from oak2026h1 and xenon2026h1 do not assert coverage until the 7th. As such, the ‘revoked’ status is masked by an ‘unknown’ status, as in Bug #367. … This problem will more or less resolve itself once CAs start logging precertificates to static CT logs.”
mozilla/crlite issue 376, comment by jschanck · saved crlite-issue-376-comments.json
Exhibit 6 · The filter’s own coverage list
$ inspect 20261002-1-default.filter.delta (clubcard-crlite example)
Clubcard of size 135568 (108208 + 27360) with 0 exceptions
CT Log ID Min Time Max Time
utuIpG+cr6QJDoLlk1bbbni0pT9YLbCBl5UkLym2jJg=, 0, 1790946101346
...
1,078 entries; 44 match a log on the Google or Apple log lists.saved coverage-20261002-1-default.delta.txt and coverage-20260902-0-default.filter.txt · filter files 20260902-0-default.filter, 20261002-1-default.filter.delta
Our questions to Mozilla
Sent to Mozilla’s CRLite maintainers on 2 October 2026 (mozilla/crlite issue 391). Answers will be printed here as written.
- When is the next full filter due? The current snapshot is dated 2 September; the Clubcards paper describes a new one about every 22 days.
- Is the figure in our sample, 37 of 108 certificates revoked within 24 hours of issuance showing as good, in line with Mozilla’s own telemetry?
- Issue 376 says the gap resolves as CAs move to static logs. Is Mozilla tracking how many newly issued certificates still carry only 24-hour-log timestamps?
- Is there a plan to include the uncovered revocations in a delta once their coverage window closes, rather than waiting for the next snapshot?
- The coverage list omits 25 of the 68 logs the Google and Apple programs currently qualify, including Cloudflare’s Raio, Geomys’ Trastevere and GoDaddy’s Aquamarine. Is that intended, and what happens to a certificate logged only to those?
- Should the blog’s “all certificate revocations” be read as applying to desktop only, given Android’s channel carries three reason codes?
Their reply, scored
Disclosure timeline
| 2 Oct | Published; sent to Mozilla with the six questions above, as mozilla/crlite issue 391 and by email to the CRLite maintainer. |
Waiting on Mozilla since 2 Oct.
What we can’t be sure of
- The headline rests on the 465 certificates whose final form is public. They skew toward CAs that log final certificates, and within-24-hour revocations are 23% of them. The other 602 point the same way (5 good, 563 revoked) but their timestamps come from crt.sh, which had not ingested some logs for 34 of them, so their “not covered” count is ours to doubt, not Firefox’s.
- This is a sample of revocations, not of browsing. A certificate revoked two minutes after issuance is usually a reissue nobody will ever visit. We don’t know how often a Firefox user meets one of the 38.
- Firefox also honours an OCSP response stapled by the server, and extra timestamps sent in the TLS handshake. We tested the certificate as served to Certificate Transparency; a server that staples could get a different answer.
- Mozilla’s description says the gap closes at the next full filter. We measured one point in time, 30 days after the last one. A snapshot published tomorrow would change the count to zero, until the next first-day revocation.
- Our sample draws equally from organisations, so small CAs weigh as much as Let’s Encrypt. The 38 come from 16 of 86 organisations.
Run it yourself
Python 3 with cryptography, a PostgreSQL client for crt.sh’s public mirror, and Rust for Mozilla’s tools. The CRL pass takes about ten minutes; crt.sh is slow and sometimes refuses connections, so the lookup can take an hour.
python3 sample_crls.py && python3 sample_crls_big.py # CRLs from CCADB, revocations 2-30 days old python3 fetch_and_query.py # draws the sample (the fetch inside it is superseded) python3 fetch_v3.py && python3 fetch_scts.py # crt.sh lookups, SCT timestamps in UTC git clone https://github.com/mozilla/crlite && git apply exhibits/rust-query-crlite-raw-subcommand.patch cargo build --release --manifest-path crlite/rust-query-crlite/Cargo.toml rust-query-crlite -d db_default --update prod --channel default https example.com rust-query-crlite -d db_compat --update prod --channel compat https example.com python3 analyze.py # verdicts, tables, results.json
Reproduced from the public repository on 3 October 2026 on a clean machine: the CRL sample and the Firefox query tool build and run (1,320 CRLs parsed, 255,797 revocations in the window, example.com Good against 63 filters). The crt.sh lookups for 1,691 certificates take about an hour. Full table on the track record.
What you can do with this
- If a certificate you rely on is revoked within a day of issuance, Firefox may still accept it for up to a month; staple OCSP or rotate the name.
- If you issue certificates, log to a tiled log too; Firefox's filter reads those within a day.
References
- Bobby Holley. Fast, private and secure (pick three): Introducing CRLite in Firefox. Mozilla, 19 August 2025. blog.mozilla.org.
- Firefox source,
security/certverifier/NSSCertDBTrustDomain.cpp,CheckRevocation. github.com/mozilla-firefox/firefox. - Firefox source,
modules/libpref/init/StaticPrefList.yaml:security.pki.crlite_mode,security.pki.crlite_channel; mozilla/crliterust-query-crlite/README.mdon the two channels. - John Schanck. mozilla/crlite issue 367, “Certificates revoked within one CT log MMD of issuance can fail to appear as revoked in delta updates”, 16 September 2025.
- mozilla/crlite pull request 369, “storage: hold serials in cache until they are covered”, merged 25 September 2025.
- mozilla/crlite issue 376, “revoked-isrgrootx1.letsencrypt.org not showing up as revoked”, 13 November to 5 December 2025.
- John M. Schanck and others. Clubcards for the WebPKI: smaller certificate revocation tests in theory and practice. IEEE S&P 2025. research.mozilla.org.
- CCADB, Mozilla intermediate certificates with CRL URLs, MozillaIntermediateCertsCSVReport; crt.sh public database,
crt.sh:5432/certwatch; Google and Apple CT log lists.
Cite as
@misc{markovian-sm009,
author = {{Markovian Protocol}},
title = {Firefox CRLite against the CAs' own revocation lists, October 2026},
number = {SM-009},
doi = {10.5281/zenodo.23123001},
year = {2026},
month = oct,
url = {https://markovianprotocol.com/measurements/sm-009.html}
}