Last updated: 21 October 2026. This is a developing incident.
The eMudhra certificate compromise is a key-generation flaw, not an intrusion. According to Mozilla, the private keys of eight intermediate certificate authority (CA) certificates could be recovered from public data, so they could no longer be treated as secret. Browsers were protected within hours. The servers, containers and scripts that call your APIs only get that protection when someone updates their trust store.
This post separates what is confirmed from what we think. Sections 1 to 4 are facts, attributed to their sources. Sections 5 to 7 are NoMoreBreach’s analysis, labeled as ours. This analysis is based on public records, and the details may change as the incident develops.
1. What happened, in 90 seconds
A terminology note first. In the web PKI (the system of certificate authorities browsers trust), “key compromise” means a private key can no longer be assumed to be under the CA’s exclusive control. Here, per Mozilla, that is because the keys could be computed from public data. It is not a claim that anyone broke into eMudhra. eMudhra states its infrastructure was not compromised and that no data was breached.
According to Mozilla’s incident bug (2083449), eight eMudhra intermediate CA certificates had recoverable private keys. Six are TLS intermediates trusted by the Chrome, Mozilla, Microsoft and Apple root programs. Two are code-signing intermediates trusted by Microsoft.
They were created in a key generation ceremony on 30 April 2025, as part of a batch of 24. The affected keys are the P-384 keys of the “B” and “C” series. Mozilla’s analysis: “The 8 impacted keys all used integers less than 256. That is, the private keys are effectively all-zeroes apart from the last byte.”
What went wrong in the process is not settled. Two accounts exist, and we present both:
- Google says the keys “were generated with insufficient randomness (i.e., weak cryptographic entropy).”
- eMudhra’s preliminary account is that “a key wrap/unwrap step produced a second, weak set of keys alongside the original strong keys,” and that the weak keys were the ones published to the root stores. eMudhra also says: “We have not yet confirmed the exact root cause.”
On issuance, eMudhra states that seven of the eight intermediates were never in production and that the eighth “had not issued a single certificate.” Chrome says no TLS certificates chaining to the six TLS intermediates were logged to Certificate Transparency (CT) before it blocked them.
The consequence: Mozilla and Chrome are removing the upstream root, emSign ECC Root CA – G3, and eMudhra has stopped issuing from every intermediate chaining to it. Only that root is being removed for this incident.
On scope, eMudhra’s public statement and its press release filed with NSE and BSE (we read the NSE copy) say its India DSC and eSign businesses are unaffected and run on separate infrastructure, and that its global TLS business is “around 1% of the company’s revenue.”
2. Why a weak key on an intermediate affects the whole web
Clients trust roots. Roots sign intermediates. Intermediates sign site certificates. A client accepts a site certificate if it chains to a trusted root.
So whoever holds a trusted intermediate’s private key can sign a certificate for any name. Mozilla says such keys “could allow attackers to issue fraudulent HTTPS certificates for websites they do not control.” Cloudflare puts it as: “an attacker can create a forged certificate for any domain.”
Why does “it never issued anything” not make it safe? In our reading, the risk is future forged certificates signed with a recoverable key, not past issuance. That is why the intermediates, and then the root, had to be distrusted.
Why is the key recoverable? A P-384 private key should be a random integer up to roughly 2^384. If it is below 256, there are at most 255 candidates. Mozilla says the keys “can be recovered near instantly via the baby-step giant-step discrete log algorithm or more simplistically by just generating the ‘first’ 256 P384 keys.”
This is not a break of ECDSA or P-384. Mozilla said the flaw was in “the original key generation,” “rather than any issue with the produced signatures.” Cloudflare makes the same distinction: the problem is certificate-based authentication with weak keys, not TLS’s encryption algorithms.
On AI, a Mozilla engineer reported that local AI agents recovered a key “on their first attempt with a simplistic prompt.” The point is how small the search space is, since any tool can try 255 candidates. No source establishes what tooling the original reporter used, so this is not an “AI attack” story.
3. Timeline: how the ecosystem responded
Times are UTC, taken from the root programs’ records (Bugzilla 2083449, the Mozilla dev-security-policy thread, Mozilla’s security blog, and Google’s blog) unless marked as eMudhra’s statement or a community tracker.
| When (UTC) | Event |
|---|---|
| 2025-04-30 | Key generation ceremony creates 24 intermediates, including the 8 affected P-384 keys. |
| 2025-05-29 to 06-06 | CRLs (certificate revocation lists) for the 6 affected TLS intermediates are published with invalid signatures. Sectigo reports it (Bug 1970728), and corrected CRLs are republished on 6 June 2025. |
| Mid-2025 | Hierarchy included in browser trust lists. eMudhra states it “has since passed two independent audit cycles.” |
| 2026-10-17 18:05 | A researcher reports to Apple, Chrome, Microsoft, Mozilla and eMudhra. Chrome confirms it received the report at 18:05. |
| 2026-10-17 19:45 | Chrome ships a CRLSet update blocking the SPKI hashes (public-key hashes) of the 6 TLS intermediates. This also covers Sectigo cross-certificates that share those keys. |
| 2026-10-17 20:06 | Mozilla receives the report, forwarded by the Chrome Root Program. |
| 2026-10-17 21:29 | eMudhra acknowledges the report and notifies Sectigo. |
| 2026-10-17 21:48 | Mozilla independently recovers the keys “without any knowledge of the method the original reporter used.” |
| 2026-10-17 22:59 | Mozilla’s OneCRL block reaches all standard-configuration Firefox users, “less than 3 hours” after the report. |
| 2026-10-18 09:24 to 09:38 | eMudhra revokes all 8 intermediates, reason cACompromise. |
| 2026-10-18 12:06 | Mozilla opens Bug 2083449 (restricted at first, made public 20 Oct). |
| 2026-10-19 13:43 | eMudhra posts a preliminary root-cause account in the bug. |
| 2026-10-19 14:55 | Sectigo completes revocation of its cross-signed copies. |
| 2026-10-19 | Go 1.27.3 and 1.26.10 are released with a crypto/x509 security fix (CVE-2026-111943). rustls webpki-roots 1.0.10 removes emSign ECC Root CA – G3. |
| 2026-10-19, about 22:00 | Android devices get an equivalent block via Google Play Services, per Google. |
| 2026-10-19 / 20 | Apple platforms reportedly blocked from 19 Oct, Microsoft from 20 Oct, according to a community tracker maintained by a Mozilla engineer. We found no first-party Apple or Microsoft notice. |
| 2026-10-20 | Mozilla says “multiple individuals have independently recovered the private keys” and announces emergency removal of trust in emSign ECC Root CA – G3. It is “not removing trust in emSign Root CA – G1” “at this time.” |
| 2026-10-20 | eMudhra ceases issuance from all intermediates under G3. It estimates “about 30,000 certs that require migration and about 97% came via ACME,” moving to its G1 (RSA) hierarchy. |
| 2026-10-20 | The Chrome Root Program says Chrome “has committed to a similar path as described by Mozilla.” NSS 3.131.1 ships with the G3 root removed. Firefox 158.0.1, ESR 115.43.1 and ESR 153.5.1 are released. |
| 2026-10-21 | eMudhra files a press release with NSE and BSE. Firefox for Android 158.0.2 ships a fix for a blocklist-at-startup issue. |
| 2026-10-27 (planned) | Google says Chrome’s removal of emSign ECC Root CA – G3 is expected “Tuesday morning, October 27, 2026 PDT.” As of today it has not happened. |
Why browsers were fine
Chrome enforces CT by default. In the Chrome Root Program’s words: “Because no TLS certificates chaining to these six intermediate CAs were logged to CT prior to our CRLSet block on October 17, no fraudulent certificates issued by these CAs could have been trusted by default in Chrome or other CT-enforcing browsers.”
Chrome blocked by key (SPKI hash), not by certificate. The same weak keys appeared in eMudhra-issued and in Sectigo cross-signed certificates, and one block covered both. Chrome says it did not need to block the two code-signing intermediates, because its verifier does not build TLS paths through code-signing-only intermediates.
Chrome also says it “found no other instances of this failure mode” in its trust boundary, and Mozilla says “at this time we do not believe the issue impacts other CAs.”
The response deserves credit. Root programs blocked the keys in hours and published their reasoning. eMudhra acknowledged the report within hours, revoked all eight intermediates the next morning, and said publicly: “We acknowledge this incident and take full responsibility for it.”
4. Where exposure remains: non-browser clients
Mozilla’s concern is that “many endpoints do not have effective mechanisms for getting revocation information.” That is why the root was removed: it “will protect clients which do not use revocation information or lack a mechanism to withdraw trust in specific intermediates.”
Mozilla’s guidance to trust-store operators is that if clients “reliably check revocation information and fail-closed,” no action is needed. Otherwise, block the listed intermediates or consider removing the roots.
Root removal cuts both ways. Mozilla says the NSS change “will impact the availability of some servers for those non-Firefox users until those servers move to new certificate chains.” Google says “some legitimate certificates chaining to this root will cease to function in Chrome.”
A hard-coded denylist in Go
Every ecosystem ships its own trust store, and fixes landed separately. Go’s is CVE-2026-111943. Per its NVD description, “in some narrower cases, the system trust stores may not be updated without further action,” so Go added a denylist in crypto/x509 that returns an error when calling Verify with any of the known intermediates. Affected versions are before 1.26.10, and 1.27.0 up to but not including 1.27.3. NVD lists the status as “Received,” with no CVSS score at the time of writing. See also the Go issue.
One stock host we tested
As an example, not a statistic: on 21 October we tested a stock, unpatched Ubuntu 26.04 host (ca-certificates 20260601~26.04.1, curl 8.18.0). It returned HTTP 200 from a test host operated by a Mozilla engineer, which means it still trusted the affected chain. The community tracker lists the patched Ubuntu 26.04 package as 20260816ubuntu0.26.04.1. Check your vendor’s own advisory.
An independent researcher, in a blog post, reports that default curl, Python and Node on Linux and macOS accepted a test certificate under this chain before updates. That is a secondary source, not a root-program statement.
Exploitation: what is and is not known
No source we read reports in-the-wild misuse, and none shows evidence that there was none. Cloudflare says: “Our security review has not identified active exploitation of this issue on Cloudflare services.” eMudhra says: “We are not aware of any evidence that the weak keys were recovered or exploited by anyone before the issue was disclosed.” The community tracker says: “We do not know if attackers exploited the flawed key generation.” We cannot say more than that in either direction.
5. Lesson 1 (our view): your trust store is attack surface
From here on, this is NoMoreBreach’s analysis, not a statement about eMudhra.
Inventory where your TLS trust comes from. Likely places: OS bundles in base images, language bundles (certifi, Node’s bundled roots, Java cacerts), statically compiled binaries (Go, Rust with webpki-roots), mobile apps, edge and IoT firmware, and third-party SDKs and agents. Each updates on its own schedule.
Update, rebuild, redeploy. Patching a package on the host does not fix a container image built last month. Upgrading Go does not fix a binary you have not rebuilt, because the fix lives in the standard library that is compiled in. Cloudflare’s advice: “Validate through the application’s actual TLS path,” because “a successful browser test does not prove that a background service is protected.”
Never fix the resulting errors by turning verification off. Cloudflare: “It’s important to not resolve these errors by disabling verification.” In our experience, disabled verification (verify=False, InsecureSkipVerify: true, NODE_TLS_REJECT_UNAUTHORIZED=0) is a recurring pentest finding in internal service calls and webhooks. In an incident like this one, it removes the one control that would have helped.
Illustrative example, defensive, for your own systems. This uses a Mozilla-run test host whose chain uses an affected eMudhra intermediate. Expected result on a patched system: a certificate error.
# ILLUSTRATIVE - defensive, for your own systems.
# PATCHED trust store -> curl fails with a certificate error (good)
# UNPATCHED trust store -> HTTP 200 (you still trust the affected chain)
curl -sS -o /dev/null -w "%{http_code}\n" https://dv-g3b-emudhra.we-have-a-problem.com/
# Run it INSIDE the thing that matters, not on your laptop
# (your-api-image:prod is a placeholder; if the image has no curl,
# run the equivalent check in the app's own runtime):
docker run --rm your-api-image:prod \
curl -sS -o /dev/null -w "%{http_code}\n" https://dv-g3b-emudhra.we-have-a-problem.com/
# Language-level bundles update separately from the OS:
python -c "import certifi; print(certifi.__version__)" # tracker lists a fixed version: 2026.10.19 or later
go version # fixed: go1.26.10 / go1.27.3 or later, THEN rebuild
# Anti-pattern: never "fix" the resulting error like this
# requests.get(url, verify=False) # Python
# tls.Config{InsecureSkipVerify: true} # Go
Updating can also break outbound calls to a partner that still serves a G3 chain. Plan for that failure mode before you roll out.
6. Lesson 2 (our view): CA agility is vendor-risk management
Your CA is a vendor, and vendors have incidents. Google tells operators with certificates on the affected hierarchy that they “must immediately acquire and install a new TLS certificate” from another hierarchy.
Automation makes migration cheap. eMudhra estimated that about 97% of the roughly 30,000 certificates needing migration were issued via ACME (the automated issuance protocol). Our view: if issuance is automated and your config can point at a second CA, a distrust event becomes a config change instead of an outage. eMudhra says it is now offering Enterprise TLS customers certificates “from an additional publicly trusted CA.”
Know what CAA and CT monitoring do here, and what they do not.
- CAA records tell honest CAs which CAs may issue for your domain. They are checked by the issuing CA, not by clients, so they do not stop someone holding a trusted intermediate’s key from signing a certificate offline. Keep them, but do not count them as protection against this kind of event.
- CT monitoring shows certificates that get logged. A forger targeting clients that do not enforce CT has no reason to log. CT enforcement in browsers is what protected browser users here.
Pinning is a trade-off. For clients you fully control, such as your mobile app calling your API or service-to-service calls, pinning to your own keys or a private CA limits which CAs can impersonate you. The cost is lockout risk if you rotate badly. Treat it as an advanced option with a documented rotation and backup-pin plan, not a default.
Ask your vendors one question: “How fast can you ship a trust-store update to the agents, SDKs and appliances you have deployed in our environment, and how will we know it landed?” Cloudflare had to ship WARP, 1.1.1.1 and cloudflared updates, and said “some customers will need to take action on software or trust configurations that they operate.”
7. Lesson 3 (our view): if you run your own PKI, verify keys, not labels
Many startups run a private CA for mTLS, a code-signing key, or token-signing keys in an HSM or cloud KMS. “It is in an HSM” does not cover the procedure around the HSM. eMudhra states its keys were generated on FIPS 140-2 Level 3 HSMs and that “the problem was a flaw in one step of the ceremony procedure, not the absence of HSMs.” Its preliminary account in the bug describes a weak second key pair being “used by mistake to create the csr (because the key labels were similar).”
Control: bind the CSR to the intended key by fingerprint, not by label. Before signing, compare the CSR’s public-key fingerprint with the fingerprint of the key you meant to use, and have a second person check (maker/checker).
Treat verification failures as alarms. In June 2025, CRLs for the same six intermediates failed signature verification (Bug 1970728). In the 2026 bug, eMudhra’s account is that the CRLs “were signed with the original private keys (which were supposed to be the correct keys with appropriate entropy) but given that this resulted in incorrect signatures, they were resigned with flawed keys.” Mozilla noted: “It seems unlikely that the exact same intermediate set has arisen in two different bugs by chance.” These are quoted accounts, and we draw no conclusion from them about anyone’s diligence. The general lesson is ours: when a signature does not verify against the published key, find out why before making it pass.
Test for failure modes adversarially, not only for compliance. eMudhra states the hierarchy “passed two independent audit cycles” and that the issue “went undetected for about 18 months.” Audits check that documented controls exist and run. Adversarial testing asks what breaks if an assumption is wrong. Both have a place.
Illustrative example, defensive, run against your own keys only. The Python check detects only the specific tiny-scalar failure described above, not weak randomness in general. On 21 October we ran it with Python cryptography 50.0.0: a synthetic key with a tiny scalar was flagged, a freshly generated P-384 key passed, and both took under 0.1 seconds together. Do not point it at anyone else’s certificates.
# ILLUSTRATIVE - defensive, for your own systems.
# 1) Bind CSR to the intended key by FINGERPRINT, not label (maker/checker compares)
openssl req -in intermediate.csr -noout -pubkey | openssl pkey -pubin -outform DER | sha256sum
openssl pkey -pubin -in intended-key.pub.pem -outform DER | sha256sum # must match
# ILLUSTRATIVE - defensive, for your own systems.
# 2) Self-audit your own EC public keys for the "tiny private scalar" failure mode.
from cryptography.hazmat.primitives.asymmetric import ec
def has_tiny_scalar(pub: ec.EllipticCurvePublicKey, limit: int = 1 << 16) -> bool:
target, curve = pub.public_numbers(), pub.curve
return any(
ec.derive_private_key(d, curve).public_key().public_numbers() == target
for d in range(1, limit)
)
# Returns True only for this specific failure. False does NOT prove the key is strong.
What we don’t know yet
- The final root cause. eMudhra says it will publish its root cause “in full once our investigation is complete,” and Mozilla is still asking questions in the bug.
- Whether anyone exploited the keys before disclosure. See Section 4.
- The future of eMudhra’s remaining trusted root. Mozilla is not removing emSign Root CA – G1 “at this time,” and Chrome is “conducting a thorough evaluation regarding the status of eMudhra’s remaining CA certificate.” We make no prediction.
- Apple’s and Microsoft’s exact actions. We found no first-party notice, only the community tracker’s dates.
- How many users or systems were affected. eMudhra says certificate replacement impact is “contained to a single customer ecosystem in the United States,” and separately estimated “about 30,000 certs” needing migration. Both are eMudhra’s figures from different documents, and we have not reconciled them.
A five-minute self-check
- Do all our production images and hosts reject the Mozilla test host? Did we check inside the containers, not on laptops?
- Have we rebuilt Go and other statically linked services with patched toolchains and root bundles?
- Is TLS verification disabled anywhere in our code, CI or webhooks?
- If our CA were distrusted tomorrow, could we switch CAs via ACME without downtime? Have we tested a second CA?
- If we run a private CA or signing keys, do we bind CSRs to keys by fingerprint, with maker/checker review?
Not sure which of your internet-facing services and dependencies would trust a forged certificate, or which still have TLS verification switched off? Start with our free external attack-surface snapshot. It needs no access and costs nothing.
Want us to test whether your APIs, webhooks and service-to-service calls actually validate certificates, and how your stack holds up during a CA distrust event? Book a scoping call.
Sources
All read on 21 October 2026. This post will be updated as the incident develops.
- Mozilla Bugzilla 2083449, private key compromise of eMudhra intermediate certificates
- mozilla.dev.security.policy thread (Mozilla and Chrome Root Program posts)
- Mozilla Security Blog
- Google: Protecting Chrome and Android users from compromised eMudhra intermediate CA certificates
- eMudhra statement on the certificate security incident
- eMudhra press release filed with NSE and BSE, 21 October 2026 (NSE copy)
- Cloudflare: 8 eMudhra certificates are compromised
- NVD: CVE-2026-111943 and the Go issue 82345
- Bugzilla 1970728, eMudhra invalid CRL signatures (June 2025)
- Secondary: community tracker and test hosts maintained by a Mozilla engineer; independent researcher’s blog post
- First-hand: NoMoreBreach lab checks and snippet tests, 21 October 2026
