Eight eMudhra intermediate CAs were revoked on 18 October 2026 with the reason code a CA uses when it believes its private key is in the wrong hands. Mozilla, Sectigo and the Go team each acted on it within 48 hours. None of them, and not eMudhra, has said what happened.
We went looking at eMudhra because of a dull Bugzilla thread about root transition plans. We came back with this. What follows is the public record as of 20 October, with the facts kept apart from the inferences, because the gap between the two is the whole story right now.
Who eMudhra is
eMudhra is an Indian certificate authority, listed on the Bombay and National stock exchanges. Its public TLS brand is emSign, and its roots are in the Mozilla, Chrome, Apple and Microsoft stores. In April 2025 it created a new batch of issuing CAs under two of its roots, one for TLS and one for code signing, split by region. The “G3A” series belongs to the Indian parent. “G3B” belongs to eMudhra BV, a Dutch entity. “G3C” belongs to eMudhra Inc, a US one. Each region got a DV, an OV and an EV TLS issuer, plus an OV code signing issuer.
The eight that matter are the Dutch and US ones:
| CA | Operator | Parent root | SHA-256 fingerprint (first 16) |
|---|---|---|---|
| EM DV TLS CA - G3B | eMudhra BV (NL) | emSign Root TLS CA - G3 | 42C4ACCD12C4F595 |
| EM OV TLS CA - G3B | eMudhra BV (NL) | emSign Root TLS CA - G3 | 98B896625C0C230A |
| EM EV TLS CA - G3B | eMudhra BV (NL) | emSign Root TLS CA - G3 | E7568FE6E12331F4 |
| EM OV CS CA - G3B | eMudhra BV (NL) | emSign Root CS CA - G3 | 9E39DE2881273ACC |
| EM DV TLS CA - G3C | eMudhra Inc (US) | emSign Root TLS CA - G3 | 0164D7CEAE5BB909 |
| EM OV TLS CA - G3C | eMudhra Inc (US) | emSign Root TLS CA - G3 | CB6E15165AC802E9 |
| EM EV TLS CA - G3C | eMudhra Inc (US) | emSign Root TLS CA - G3 | 432EC25F0D28DE90 |
| EM OV CS CA - G3C | eMudhra Inc (US) | emSign Root CS CA - G3 | 4B2460A466F95FD4 |
All eight were created on 30 April 2025 with a validity to 2040. All eight were also cross-signed two weeks later by Sectigo from its AAA Certificate Services root, which is how a young CA gets its certificates accepted by old devices that have never heard of it.
What happened, in order
On Friday 17 October at 22:00 UTC, Mozilla’s OneCRL, the blocklist Firefox fetches in the background, gained entries for the six TLS intermediates. Each entry cites a Bugzilla bug that returns “not authorized” to anyone without privileged access. Mozilla’s CA program runs in the open, and hidden CA bugs are rare enough that we can’t name another. The hiding is itself a signal.
On Saturday 18 October, between 09:24 and 09:38 UTC, eMudhra’s two root CRLs added all eight CAs. The Common CA Database, where every publicly trusted CA has to disclose its intermediates, records the reason for every one of them as cACompromise. That is eMudhra’s own declaration, RFC 5280 reason code 2, and it has one meaning: the CA believes the private key is no longer solely under its control.
On Sunday 19 October, Sectigo revoked its eight cross-certificates to the same keys, also with reason cACompromise. The same day, the Go team opened an issue titled “mitigation for security concerns with a specific Certificate Authority”, put it on the urgent track, assigned CVE-2026-111943, and released Go 1.27.3 and 1.26.10. The patch is about thirty lines:
// distrustedSPKIHashes contains hashes of SPKIs from certificates which
// we don't consider to be trustworthy. We use these hashes to filter out
// chains returned by Verify
var distrustedSPKIHashes = map[string]struct{}{
"ebed6475c2c2d80fcb199f3fe8dd6e6b3ce60b77eb15d4e42c3dec0c6f5b5105": {},
"49dd353dc2b919a3770645117d0e60c16115e7d1bc259eefe734b00ea434fe5f": {},
// ... six more
}
func containsDistrustedSPKIHash(chain []*Certificate) bool {
for _, c := range chain {
h := sha256.Sum256(c.RawSubjectPublicKeyInfo)
if _, ok := distrustedSPKIHashes[hex.EncodeToString(h[:])]; ok {
return true
}
}
return false
}
Every chain containing one of those eight public keys now fails verification, on every platform, including when Go hands the chain to the Windows or macOS verifier and gets a result back. The commit doesn’t say whose keys they are. Within hours a community member on the issue matched all eight hashes to the table above.
By Monday 20 October, nothing had been added. No incident report on Bugzilla, which is where Mozilla policy requires one. Nothing on eMudhra’s repository site, which was last updated on 17 October with a routine practice statement revision. No exchange filing. No press. The public record is a Go issue thread, a CCADB export, and two CRL files.
What compromise means here, and what it doesn’t
Reason code 2 says the key is believed exposed. It doesn’t say how, and nobody has. A lost HSM backup, a hostile insider at one of the subsidiaries, a managed service provider holding a copy of something it shouldn’t, a misconfigured key ceremony: all of these fit. Eight CAs across two legal entities going at once suggests a shared system rather than one bad key, but that is our inference and we’re labelling it as one.
The shape of the Go response is the part worth dwelling on. Go does no revocation checking by default. No CRL fetch, no OCSP, no OneCRL equivalent, and no Certificate Transparency enforcement. If someone used a compromised intermediate to mint a certificate for your API host and never logged it anywhere, a browser would refuse it for lack of CT proofs. A Go client would accept it, because the chain reaches a trusted root and that’s the whole test. The only lever the Go team had was a point release with the keys burned into the binary. It’s an ugly fix. It’s also the right one, and the fact they reached for it on a weekend, with a CVE, tells you how seriously they took whatever they were told.
Mozilla pushing its block eleven hours before the CA’s own CRL tells you the same thing. Somebody informed the root programs privately, the programs acted, and the disclosure is lagging the response.
What Certificate Transparency shows: nothing
We checked whether these eight CAs had ever issued a certificate that reached the CT logs. They haven’t. Zero certificates, ever, across eighteen months, for all eight. The Dutch entity’s older “G2B” CAs are also at zero. The Indian parent’s equivalent CAs are busy, with tens of thousands of DV certificates, the most recent issued hours before the revocation.
Two readings. The charitable one is that eMudhra BV and the US G3 CAs hadn’t launched: the keys existed, were cross-signed, were disclosed, and sat idle. The uncharitable one is that something was issued and never logged. CT only records what a CA chooses to submit, and a party holding a stolen key has no reason to submit anything. There is no public evidence for either, and that absence is exactly why Go couldn’t lean on CT and had to hardcode the hashes.
For defenders the upshot is blunt. There is nothing to hunt for in the logs. If something was issued from these keys, it won’t be there.
The rest of the picture
This didn’t happen in a vacuum. Since mid September, outside researchers have filed close to ten incident reports against eMudhra with Mozilla: subscriber certificates with key sizes its own practice statement forbids, delegated OCSP responder certificates with a forbidden extension, certificates one second over their maximum validity, missing policy identifiers, seven undisclosed subordinate CAs with no EKU under a root that was supposed to be on its way out, and a practice statement that hadn’t kept up with the requirements it claims to follow. Each of those on its own is routine. The rate isn’t.
At the same time eMudhra had ten new root certificates in the inclusion pipeline. The six-week public discussion closed on 17 September with no objections. Mozilla published a notice of intent to approve on 6 October. Eleven days later it was pushing a block for the company’s intermediates. On 19 October eMudhra also asked Mozilla to remove two of its older US roots outright, a request that had been sitting as a vague “may be distrusted” since April.
We don’t think the compliance stream and the compromise are the same event. Linting failures and a stolen key are different failure modes. But they say something about how much attention a CA is paying, and the root programs will read them together.
What to do
If you run Go services that make outbound TLS connections, update to 1.27.3 or 1.26.10. That is the whole mitigation on your side.
If you’re a browser user, Firefox already blocks the keys. Chrome presumably does too through its own blocklist, though Chrome hasn’t said so in public either.
If you run TLS inspection at the edge, a UTM, a web proxy or a next-generation firewall that terminates and re-signs outbound connections, treat that box the way the Go team treated its standard library. Most middleboxes validate against a vendor-shipped trust store, fetch CRLs on a schedule or not at all, and know nothing about OneCRL or Certificate Transparency. Until the vendor pushes an update, the eight keys are still trusted there. Add them to the device’s untrusted or blocked certificate list by public key hash where the product supports it, which covers both the emSign-issued certificates and the Sectigo cross-signed ones in a single entry each:
ebed6475c2c2d80fcb199f3fe8dd6e6b3ce60b77eb15d4e42c3dec0c6f5b5105 EM DV TLS CA - G3B
43bffa19d6ef651451f6841e019931e96f6f2eaeff28ab4b6f1ce4576de2717b EM OV TLS CA - G3B
e0254c7fcdc265e2f0f8a428dabb75ab4ae039b4872d62f5ee57f0877d5a8a41 EM EV TLS CA - G3B
ec4ffa1ad0ac88081314b7aaffef6a91f97cd57291bb5ba686c5415f5eb4f6b6 EM OV CS CA - G3B
49dd353dc2b919a3770645117d0e60c16115e7d1bc259eefe734b00ea434fe5f EM DV TLS CA - G3C
63ecefee431d49523bc1136c4e72d0206a477086caf606cd5cf025686c109cf8 EM OV TLS CA - G3C
5c0660a2b164910d8ff589c18e14552e9e0ec237dcefe2cb736d41a4811f81a0 EM EV TLS CA - G3C
92c063d67e8f14db71d288e11266ffdaf69cbf115f7bab14f3bc2f68d25e0e30 EM OV CS CA - G3C
Those are SHA-256 hashes of each CA’s subject public key info, the same values Go ships. If the product only blocks by certificate fingerprint, you need sixteen entries: the eight certificates in the table above plus the eight Sectigo cross-certificates, all listed in the CCADB revoked intermediates export linked earlier. Blocking the emSign roots outright is a bigger call. It would cut off every emSign India customer too, and nothing public says those CAs are affected. If your organisation has no dependency on emSign, that trade-off may be acceptable until the incident report explains the scope. If it does, block the eight and wait.
If you bought a certificate from eMudhra BV or eMudhra Inc, you didn’t, as far as the logs show. If you bought one from emSign in India, the revocations don’t touch your issuing CA. We would still watch for the incident report, because nobody has stated the scope of what was compromised. Eight intermediates were revoked. Whether more was exposed is an open question.
If you run a CA: this is what the reason code is for. eMudhra used it honestly, and that one bit is the reason the rest of us can see anything at all. Now write the report.
We’ll update this post when it lands.
