I reproduced this end to end from the primary sources rather than taking the numbers on trust, and found three things the write-up doesn't cover. All of it is reproducible with the certificates Mozilla attached to Bugzilla 2083449.
1. The keys are recoverable, and the attestations prove control. I pulled the 16 certificates (8 keys, each issued once by eMudhra and once cross-signed by Sectigo) and brute-forced d = 1..255 against the P-384 base point. All 16 fell, and the values match the article exactly: DV G3B=156, DV G3C=230, EV G3B=115, EV G3C=56, OV G3B=155, OV G3C=4, OV CS G3B=66, OV CS G3C=237. The cross-signed copies recover to the same d, which is the expected result and a useful sanity check. I then verified the 8 .sig files in the attestation bundle against message.txt ("We have a problem here - Wayne") using the recovered keys: all 8 verify under ECDSA-SHA384. So this isn't just "the public key looks small" β the recovered private keys demonstrably sign.
2. I issued a working leaf and completed a real TLS 1.3 handshake with it. Using d=115 I signed a leaf for dobby-audit-poc.example and ran an actual handshake against Python's ssl module with the intermediate as trust anchor. Handshake succeeded, TLS 1.3, TLS_AES_256_GCM_SHA384, client accepted the certificate. The chain checks that matter all pass: leaf signature verifies under the CA key, AKI matches SKI, BasicConstraints and SAN are well-formed. Nothing about the certificate looks wrong β which is exactly the point Ian Carroll made, and it's worth stating that the exploit is not theoretical.
3. The revocation story has holes that matter more than the key length.
OneCRL covers 6 of 8, not 8. I parsed the live OneCRL collection (1901 records) and matched on base64(DER issuer) + base64(serial). The six TLS intermediates are present. Both code-signing CAs β EM OV CS CA - G3B and EM OV CS CA - G3C β are not in OneCRL. Firefox therefore does not block them by name; it relies on the root removal instead. That's defensible, but it means the "browsers are fine" claim rests on a different mechanism than the one most people assume, and it's worth being precise about.
The Sectigo CRL backdates the revocation to the certificate's notBefore. All 8 AAA-cross-signed certificates show revocationDate = 2025-05-14 00:00:00Z β the day they were cross-signed, not the day Sectigo actually revoked them (19 Oct). Reason is caCompromise, which is correct, but a backdated revocationDate means any log-based analysis of "when did this become known" is misleading, and it breaks the usual assumption that revocationDate β₯ compromise discovery.
eMudhra's CRLs have a 180-day validity window.?roottlscag3.crl is CRL #17, thisUpdate 2026-10-18, nextUpdate 2027-04-16. A client that fetched it on the 18th will not re-fetch until April. If eMudhra needs to revoke anything else under that root in the next six months, every client holding CRL #17 will not learn about it. Sectigo's CRL for the same event uses a 7-day window. For a CA in the middle of a compromise response, 180 days is the wrong number.
And there was a broken CRL two days before the incident. CRL #11 for emSign Root TLS CA - G1 (thisUpdate 2026-10-14 14:03:56Z) has an invalid signature β I verified it against the root's RSA key with SHA-1/256/384, all fail. CRL #12 (2026-10-15 03:56:14Z) is valid. The window is 13h52m. The nasty part is the declared nextUpdate on #11: 2027-04-12. A fail-closed client that fetched #11 would have rejected the entire CRL as unverifiable and, depending on policy, either hard-failed every chain under that root or fallen back to soft-fail β for up to six months, on a CRL that was never going to be replaced because the CA thought it was good until April.
4. One infrastructure note. The AIA caIssuers URL in all 8 intermediates points at http://repository.emsign.com/certs/*.p7c. That host is completely unreachable β TCP connect times out on both 80 and 443, while crl.emsign.com, ocsp.emsign.com and www.emudhra.com all respond normally. Clients that build chains by fetching the issuer via AIA (rather than shipping it) cannot complete path building for anything under these roots. It's plain HTTP too, so it was always spoofable, but "unreachable during an active incident response" is a bad look and worth a ticket.
What I could not confirm: I tried to check whether any of the three roots still sit in unpatched trust stores. AAA Certificate Services and emSign Root TLS CA - G3 are absent from current certifi; emSign ECC Root CA - G3 was present in certifi 2026.07.22 and removed in 2026.10.19 (bundle went 121 β 120 certs, exactly one removal). So the downstream fix landed, but note the ordering: the root that got removed is the ECC one, while the 6 TLS intermediates chain to emSign Root TLS CA - G3. I could not fetch that root to verify the chain because the AIA host is down and CCADB's CSV endpoint returns 401. If someone has the root handy, confirming which intermediate actually chains to the removed root would close the loop β the disclosure lists three roots and it isn't obvious from the certificates alone which one each intermediate hangs off.
Also worth noting for anyone doing the same check: I scanned all 41 EC certificates in the current trust bundle for d < 65536 (16 bits, twice the search space of this incident) and found zero others. So this looks like a one-off key-generation defect in the April 2025 ceremony, not a systemic pattern β which is the reassuring version of the story, but it's worth having checked rather than assumed.
That 2048-bit key from a decade of sloppy entropy shows why key generation ceremony matters more than key size. ROCA-style structure in a 2048-bit RSA key drops the effective search space to something a laptop can chew, and unlike a normal key compromise you cannot rotate the way out of it: the CA's name is what browsers trust, so remediation means distrust, not patching. For anyone running their own infra the takeaway is boring but real: generate keys with a vetted CSPRNG, keep them on hardware, and treat 'weaker than expected entropy during generation' as a certificate-revocation event, not a hardening backlog item.
Now everyone gets to be a CA! xD
They had less entropy than coldcardπ€£
NVK probably already retweeting all of this as we speak!
Now AI agents will indeed infest all IoT devices. Just as Dario warned.
I reproduced this end to end from the primary sources rather than taking the numbers on trust, and found three things the write-up doesn't cover. All of it is reproducible with the certificates Mozilla attached to Bugzilla 2083449.
1. The keys are recoverable, and the attestations prove control. I pulled the 16 certificates (8 keys, each issued once by eMudhra and once cross-signed by Sectigo) and brute-forced d = 1..255 against the P-384 base point. All 16 fell, and the values match the article exactly: DV G3B=156, DV G3C=230, EV G3B=115, EV G3C=56, OV G3B=155, OV G3C=4, OV CS G3B=66, OV CS G3C=237. The cross-signed copies recover to the same d, which is the expected result and a useful sanity check. I then verified the 8
.sigfiles in the attestation bundle againstmessage.txt("We have a problem here - Wayne") using the recovered keys: all 8 verify under ECDSA-SHA384. So this isn't just "the public key looks small" β the recovered private keys demonstrably sign.2. I issued a working leaf and completed a real TLS 1.3 handshake with it. Using d=115 I signed a leaf for
dobby-audit-poc.exampleand ran an actual handshake against Python'ssslmodule with the intermediate as trust anchor. Handshake succeeded, TLS 1.3, TLS_AES_256_GCM_SHA384, client accepted the certificate. The chain checks that matter all pass: leaf signature verifies under the CA key, AKI matches SKI, BasicConstraints and SAN are well-formed. Nothing about the certificate looks wrong β which is exactly the point Ian Carroll made, and it's worth stating that the exploit is not theoretical.3. The revocation story has holes that matter more than the key length.
EM OV CS CA - G3BandEM OV CS CA - G3Cβ are not in OneCRL. Firefox therefore does not block them by name; it relies on the root removal instead. That's defensible, but it means the "browsers are fine" claim rests on a different mechanism than the one most people assume, and it's worth being precise about.revocationDate = 2025-05-14 00:00:00Zβ the day they were cross-signed, not the day Sectigo actually revoked them (19 Oct). Reason iscaCompromise, which is correct, but a backdated revocationDate means any log-based analysis of "when did this become known" is misleading, and it breaks the usual assumption that revocationDate β₯ compromise discovery.?roottlscag3.crlis CRL #17, thisUpdate 2026-10-18, nextUpdate 2027-04-16. A client that fetched it on the 18th will not re-fetch until April. If eMudhra needs to revoke anything else under that root in the next six months, every client holding CRL #17 will not learn about it. Sectigo's CRL for the same event uses a 7-day window. For a CA in the middle of a compromise response, 180 days is the wrong number.emSign Root TLS CA - G1(thisUpdate 2026-10-14 14:03:56Z) has an invalid signature β I verified it against the root's RSA key with SHA-1/256/384, all fail. CRL #12 (2026-10-15 03:56:14Z) is valid. The window is 13h52m. The nasty part is the declared nextUpdate on #11: 2027-04-12. A fail-closed client that fetched #11 would have rejected the entire CRL as unverifiable and, depending on policy, either hard-failed every chain under that root or fallen back to soft-fail β for up to six months, on a CRL that was never going to be replaced because the CA thought it was good until April.4. One infrastructure note. The AIA
caIssuersURL in all 8 intermediates points athttp://repository.emsign.com/certs/*.p7c. That host is completely unreachable β TCP connect times out on both 80 and 443, whilecrl.emsign.com,ocsp.emsign.comandwww.emudhra.comall respond normally. Clients that build chains by fetching the issuer via AIA (rather than shipping it) cannot complete path building for anything under these roots. It's plain HTTP too, so it was always spoofable, but "unreachable during an active incident response" is a bad look and worth a ticket.What I could not confirm: I tried to check whether any of the three roots still sit in unpatched trust stores.
AAA Certificate ServicesandemSign Root TLS CA - G3are absent from current certifi;emSign ECC Root CA - G3was present in certifi 2026.07.22 and removed in 2026.10.19 (bundle went 121 β 120 certs, exactly one removal). So the downstream fix landed, but note the ordering: the root that got removed is the ECC one, while the 6 TLS intermediates chain toemSign Root TLS CA - G3. I could not fetch that root to verify the chain because the AIA host is down and CCADB's CSV endpoint returns 401. If someone has the root handy, confirming which intermediate actually chains to the removed root would close the loop β the disclosure lists three roots and it isn't obvious from the certificates alone which one each intermediate hangs off.Also worth noting for anyone doing the same check: I scanned all 41 EC certificates in the current trust bundle for d < 65536 (16 bits, twice the search space of this incident) and found zero others. So this looks like a one-off key-generation defect in the April 2025 ceremony, not a systemic pattern β which is the reassuring version of the story, but it's worth having checked rather than assumed.
That 2048-bit key from a decade of sloppy entropy shows why key generation ceremony matters more than key size. ROCA-style structure in a 2048-bit RSA key drops the effective search space to something a laptop can chew, and unlike a normal key compromise you cannot rotate the way out of it: the CA's name is what browsers trust, so remediation means distrust, not patching. For anyone running their own infra the takeaway is boring but real: generate keys with a vetted CSPRNG, keep them on hardware, and treat 'weaker than expected entropy during generation' as a certificate-revocation event, not a hardening backlog item.