~/blog / security / eMudhra (emSign) CA Key Compromise: The Private Key Was the Number 4
dispatch - Security
SECURITY10/22/2637 MIN

eMudhra (emSign) CA Key Compromise: The Private Key Was the Number 4

byDhruv VakharwalaBackend & Systems Engineer

Eight eMudhra (emSign) intermediate CA keys were tiny integers anyone could recover. Full timeline, CVEs, patched versions, and how to stay protected.

⚠ TL;DR

On October 17, 2026, a researcher named Wayne found that the P-384 private keys of eight eMudhra (emSign) intermediate CAs were integers below 256 - one of them was literally 4. Anyone could recover them from the public certificates in under a second, and they had been recoverable since an April 2025 key ceremony. Browsers blocked them within hours, Mozilla dropped the emSign ECC Root CA - G3 (Chrome follows on October 27), and Go, Node.js, Python, Rust, Java and most Linux distros shipped emergency trust store fixes. Certificate Transparency kept browser users safe. Non-browser clients such as curl, Go services, Python scripts, Java apps, containers and appliances had no such protection, and many are still unpatched. Update your trust stores, rebuild your images, and never "fix" a broken chain by turning off verification.

Introduction

Every HTTPS connection you make rests on one assumption: the private keys of certificate authorities are secret, random, and impossible to guess.

A P-384 private key is supposed to be a random number between 1 and roughly 2^384, which is about 116 digits long. Nobody guesses a number like that.

On October 17, 2026, a researcher found eight CA private keys, trusted by Chrome, Firefox, Safari and Windows, that were nowhere near 116 digits.

They were 4, 56, 66, 115, 155, 156, 230 and 237.

Those are the actual private keys, not seeds or hashes. Any of the six TLS keys could sign a certificate for google.com, yourbank.com or your company's internal API, and a client that trusted eMudhra's chain would accept it.

So how does one of India's biggest certificate authorities end up protecting the web with keys you could brute-force on a calculator?

Turns out, the cryptography was fine. The process around it failed: a test step in a key ceremony, two sets of keys with similar labels, and a warning sign in 2025 that got patched over instead of investigated.

Why this one hits close to home

I work in fintech, and eMudhra is not a name I only read about in the news. In Indian fintech, eMudhra sits in a lot of places: Aadhaar-based eSign for loan agreements and onboarding, digital signature certificates for filings and approvals, and the platforms built around them. We use their services in many places across our own stack.

So reading this was horrifying. eMudhra is a listed company, a certifying authority licensed by India's Controller of Certifying Authorities, and one of the biggest names in Indian digital trust. A mistake like this is not what you expect from a company like that, and it's not something most of us ever thought to put in a vendor risk assessment.

The obvious first question for anyone in Indian fintech: are DSC and eSign affected? eMudhra says no, but for now that answer rests on eMudhra's own review. I cover it in the FAQ and in a fintech checklist below.

Let me walk through what happened, who was actually exposed, how the ecosystem patched it within a few days, and what you need to do now.


Quick Primer: Why an Intermediate CA Key Is a Skeleton Key

If you already know how the Web PKI works, skip ahead.

Your browser and your OS ship with a list of root certificates - a trust store. Roots almost never sign website certificates directly. Instead, a root signs an intermediate CA, and the intermediate signs the certificate your server presents (the leaf).

The important part: a client doesn't care which intermediate signed a certificate, only that the chain ends at a root it trusts. Unless a name constraint says otherwise, a publicly trusted intermediate can issue a valid certificate for any domain on the internet.

So whoever holds an intermediate's private key can:

  • Mint a valid TLS certificate for any website
  • Sit in the middle of a connection (public Wi-Fi, a compromised router, a malicious ISP, a hostile network) and impersonate that site
  • Read and modify traffic that looks normally encrypted to the victim
  • For code-signing intermediates: sign malware that the OS treats as legitimate software

That's why CAs generate these keys inside Hardware Security Modules (HSMs) during audited, witnessed, scripted key ceremonies. The whole Web PKI assumes this step is done right.

This time, it wasn't.


Part 1: What Went Wrong in the April 2025 Key Ceremony

On April 30, 2025, eMudhra ran a key generation ceremony that produced a batch of 24 intermediate CAs, across three series (A, B and C), two algorithms (RSA-4096 and ECDSA P-384), and four purposes: DV, OV and EV for TLS, plus code signing.

Per eMudhra's own account in the Mozilla bug and its public statements:

  • The ceremony ran on Utimaco HSMs rated FIPS 140-2 Level 3.
  • Because the keys were meant to be exported to data centres, the script included an "approved deviation to our usual KGC to test a wrap/unwrap" - a test of the key wrap and unwrap path.
  • A "flaw in the code resulted in the second pair of keys being created onboard which were weaker."
  • Those weak keys were then used "by mistake to create the csr (because the key labels were similar)," signed by eMudhra's root, and sent to Sectigo for cross-signing.

In eMudhra's October 21 press release: "A flaw in the KGC caused a wrap/unwrap step to produce a second set of weak keys alongside the original strong keys." The weak set is the one that got published to the world.

Only the P-384 keys of Series B and C were affected - eight keys in total. Series B was operated by eMudhra BV (Netherlands) and Series C by eMudhra Inc (United States). According to eMudhra, the RSA keys took a different path and the India-only Series A and A-1 were created on different (Entrust) HSMs. Mozilla said it couldn't recover the A or A-1 P-384 keys, and at the time of writing hadn't finished examining the RSA keys.

Not everyone accepts this explanation. In the Mozilla bug, Thor Simon pointed out that eMudhra's own policy says CA keys are generated in a FIPS 140-2 Level 3 device - so either the HSM was configured in a way that allowed these values, or the keys were loaded from outside. A properly functioning Level 3 HSM asked for a P-384 key does not hand you back 4. Others have asked eMudhra for the ceremony script, witness records, HSM model, firmware and CMVP certificate. eMudhra says a full root cause report is still coming.

Why this link broke: A key ceremony is supposed to be a deterministic, audited script. A "test" step that creates extra keys inside the HSM, plus human-chosen key labels that look alike, meant the wrong keys could be picked, and nothing in the process checked which ones were.


Part 2: Why the Keys Were Weak (The Math)

An ECDSA P-384 key pair is simple:

  • Private key: a random integer k between 1 and roughly 2^384
  • Public key: the point k * G, where G is the curve's fixed generator point

Going from k to the public key is easy. Going back - given the public key, find k - is the elliptic curve discrete log problem, and for a random 384-bit k it's infeasible.

But that security comes entirely from k being unpredictable. If k can only be one of 255 values, the "hard problem" becomes a for-loop:

● ● ●PYTHON
# Conceptual only: why a tiny private scalar is instantly recoverable
for k in range(1, 256):
    if k * G == certificate_public_key:  # P-384 point multiplication
        print("private key is", k)
        break

That's it. Multiply the generator by 1, 2, 3... and compare against the public key sitting inside the certificate. A 48-byte P-384 scalar with 47 bytes of zeros and one byte of key.

Here's what the eight keys actually were:

Intermediate CAOperatorPurposePrivate key
EM DV TLS CA - G3BeMudhra BV (NL)TLS (DV)156
EM OV TLS CA - G3BeMudhra BV (NL)TLS (OV)155
EM EV TLS CA - G3BeMudhra BV (NL)TLS (EV)115
EM OV CS CA - G3BeMudhra BV (NL)Code signing66
EM DV TLS CA - G3CeMudhra Inc (US)TLS (DV)230
EM OV TLS CA - G3CeMudhra Inc (US)TLS (OV)4
EM EV TLS CA - G3CeMudhra Inc (US)TLS (EV)56
EM OV CS CA - G3CeMudhra Inc (US)Code signing237

For perspective, a correctly generated P-384 key has about 3.9 x 10^115 possibilities. These had 255.

Scott Helme recovered all eight on a laptop in under a second and wrote: "One of eMudhra's certificate authority private keys is the number 4." Also: "Normally when a CA key is compromised, someone stole it!"

"Possibly with AI-assisted techniques"

eMudhra's press release said the researcher found the keys could be reverse-engineered "possibly with AI-assisted techniques."

Mozilla did note that some local AI agents recovered the keys on the first try with a CTF-style prompt. But breaking a 255-value keyspace doesn't need AI. It needs a loop and a curve library. Calling it AI-assisted makes the attack sound sophisticated, when the real problem was the keys, not the tooling.

Why this link broke: All of ECDSA's security lives in the randomness of the private scalar. The algorithm was fine - CERT-In's advisory explicitly says this "does not indicate a vulnerability in the P-384 cryptographic algorithm itself." The entropy just wasn't there.


Part 3: The June 2025 Warning Sign Nobody Chased

Here's where it gets interesting.

The problem didn't stay completely hidden for 17 months. It set off an alarm in June 2025.

In Mozilla Bug 1970728, Rob Stradling reported that crt.sh showed eMudhra CRLs for the six G3B and G3C TLS intermediates - the exact six that would later turn out to be broken - carrying invalid ECDSA signatures. A CRL signed by a CA should always verify against that CA's public key. When it doesn't, the CA is signing with a different key from the one in its certificate.

eMudhra's explanation at the time: the CRLs were "signed using incorrect CA key configuration," caused by a manual process without validation checks. It republished corrected CRLs in June 2025, added post-signing validation, and the bug was closed.

In the October 2026 bug, eMudhra explained what had actually happened. The original CRLs had been signed with the original strong keys - which don't match the public keys in the certificates, because the certificates contain the weak keys. So the "fix" was to re-sign the CRLs with the flawed keys. The signatures verified. The alarm went quiet.

An invalid signature from your own CA is about the loudest signal a PKI can give you that the certificate holds the wrong public key. It got treated as a configuration typo.

The Chrome Root Program has since asked eMudhra directly whether it knew about the key duplication back in 2025, and why it didn't notify Sectigo or the root programs. As of this writing, those questions in the bug are unanswered.

Meanwhile, the keys sat in plain view from April 30, 2025 to October 17, 2026 - roughly 17 and a half months. eMudhra's own statement says the flaw went undetected "for about 18 months through two audit cycles."

Why this link broke: The evidence was there in 2025. A signature that fails to verify should be investigated as an incident, not closed as a config fix.


Part 4: How It Was Discovered - "We have a problem here - Wayne"

On Saturday, October 17, 2026, a researcher known as Wayne ran a test over the CCADB corpus (the Common CA Database, which lists every intermediate in the major root programs) and found a break in the EC keys.

How do you prove you've cracked a CA's private key without leaking it? You sign something with it.

Wayne signed one message with the private key of each of the eight intermediates:

● ● ●TEXT
We have a problem here - Wayne

At 18:05 UTC, the report and the signed proofs went to Apple, Chrome, Microsoft, Mozilla and eMudhra. A valid signature that verifies against the public key in a CA certificate is proof of key control. Anyone can check it with OpenSSL against the published proof.zip:

● ● ●BASH
openssl x509 -in EM-DV-TLS-CA-G3B.crt.pem -noout -pubkey | diff - EM-DV-TLS-CA-G3B.pub.pem
openssl dgst -sha384 -verify EM-DV-TLS-CA-G3B.pub.pem -signature EM-DV-TLS-CA-G3B.sig message.txt

The response was fast. All times are UTC on October 17:

TimeEvent
16:27Wayne's test run finds the break in the EC keys
18:05Report and signed proofs emailed to Apple, Chrome, Microsoft, Mozilla, eMudhra
19:45Chrome corroborates and pushes a CRLSet blocking the six TLS intermediates by public key
20:06Mozilla receives the report (forwarded by the Chrome Root Program)
20:18Full CCADB check finds Sectigo's cross-signs share the same keys
21:29eMudhra acknowledges
21:48Mozilla independently recovers the keys
22:59Firefox's OneCRL block is live for standard configurations

Chrome users were protected 100 minutes after the report landed. Mozilla shipped protection to Firefox "in less than 3 hours after we received the report." Neither required users to update or restart anything.

eMudhra revoked all eight certificates (reason: caCompromise) between 09:24 and 09:38 UTC on October 18.

Mozilla's Dennis Jackson said "the impact of this incident could not be higher."


Part 5: Who Is Affected and Who Was Actually at Risk

The hierarchy: 8 keys, 16 certificates

The six TLS intermediates were issued by emSign Root TLS CA - G3, which clients reach through a cross-sign from emSign ECC Root CA - G3. The two code-signing intermediates chain to emSign Root CS CA - G3. And in May 2025, Sectigo cross-signed all eight from its AAA Certificate Services root.

A cross-sign is a second certificate for the same key. So eight compromised keys appear in sixteen certificates, with two independent paths to trust.

This matters for the fix. Removing the emSign root from a trust store does nothing for the Sectigo path. AAA Certificate Services is no longer in Chrome's or Mozilla's current root stores, but it is still trusted by Apple, Microsoft, Java's bundled cacerts, and a lot of older Linux bundles.

Browsers: shielded by Certificate Transparency

Chrome, Safari, Edge and Firefox enforce Certificate Transparency (CT): a publicly trusted TLS certificate has to be logged in public, append-only CT logs, or the browser rejects it. There are no CT entries for certificates chaining to these intermediates in the 17-month window. Google confirmed that "no fraudulent certificates issued by these CAs could have been used against CT-enforcing clients," and CT logs now reject anything chaining to them.

So an attacker who quietly found these keys in 2025 had a choice: log the forged certificate (and get caught by anyone monitoring CT), or don't (and get rejected by every major browser).

This is Certificate Transparency doing exactly what it was built for.

Everything else: exposed

The problem is everything that isn't a browser.

curl, wget, Go's net/http, Python's requests, Node.js, Java, Rust services, mobile app networking stacks, Docker images, CI runners, IoT devices, payment gateways, network appliances - most of these don't enforce CT, and most don't check revocation. They validate the chain against a trust store and stop there.

The tracking site says: "We do not know if attackers exploited the flawed key generation to target these clients." There's no public evidence anyone did. But for non-browser traffic, there's also no way to prove nobody did.

Code signing: Windows only, and no CT safety net

Two of the eight were code-signing intermediates, trusted by Microsoft. Anyone holding those keys could sign a binary that chains to a root Windows trusts, with a valid Authenticode signature and publisher name.

Code signing has no CT equivalent here, so there's no public log to check. Chrome didn't need to block these two (its TLS verifier won't build a path through a code-signing-only intermediate), but Windows did, via its automatic disallowed-certificate updates on October 20.

mTLS endpoints

Andrew Ayer pointed out that anyone with these keys could mint client certificates too. If you run an mTLS endpoint that validates client certs against public Web PKI roots, a forged client cert from one of these intermediates could authenticate to it.

The ~30,000 certificates nobody forged

Now the collateral damage.

The eight compromised intermediates barely issued anything. eMudhra says only one was ever in production (per the bug timeline, EM DV TLS CA - G3C), and none issued an end-entity certificate - which crt.sh corroborates.

But the response didn't stop at the eight. Mozilla and Chrome removed trust in the whole emSign ECC Root CA - G3, which means every legitimate certificate under that root breaks too. eMudhra estimated about 30,000 certificates need to migrate, about 97% of them via ACME, onto its emSign Root CA - G1 (RSA) hierarchy or an alternate CA.

So there are two very different groups affected:

GroupProblemDeadline
Everyone running non-browser TLS clientsMay still trust certs forged with public keysNow
Sites with certs under emSign ECC Root CA - G3Their legit certs stop being trustedChrome's root removal reaches devices October 27, 2026

Yash Kadakia of Security Brigade made the broader point: "A single authority's failure can undermine authentication for organisations that have never dealt with it."


Part 6: How Browsers, Operating Systems and Languages Patched It

Credit where it's due: the response was fast and well coordinated. Here's who did what.

Block the keys, not just the certificates

One detail in the response is worth understanding. Chrome's CRLSet blocked the intermediates by SPKI hash (the public key), not by certificate serial number. Go and Node.js shipped public key denylists. Homebrew excluded certificates by public key.

Why? Because revoking a certificate only kills that one certificate. The Sectigo cross-signs are different certificates with the same keys. Blocking the key kills every certificate that will ever carry it - including cross-signs you forgot existed.

That's also why so many Linux distros removed two roots - emSign ECC Root CA - G3 and Comodo AAA Services root. Without key-level blocking in the OS trust store, removing both roots is the only way to cut both paths.

Browsers and operating systems

VendorActionWhen
Google ChromeCRLSet blocks the 6 TLS intermediates by SPKI; emSign ECC Root CA - G3 removed in Chrome Root Store v43Oct 17; root removal Oct 27
AndroidEquivalent block via Google Play Services (restart the device to pull it immediately)Oct 19
Mozilla FirefoxOneCRL block; Firefox 158.0.1, ESR 115.43.1, ESR 153.5.1 bundle it for users with Remote Settings disabledOct 17; releases Oct 20
Mozilla NSSNSS 3.131.1 removes emSign ECC Root CA - G3Oct 20
Firefox for Android158.0.2 fixes some profiles not applying the bundled blocklistOct 21
AppleBlocks the certificates on Apple platformsOct 19
MicrosoftBlocks via Windows automatic certificate trust list updatesOct 20
SectigoRevokes its eight cross-signed certificatesOct 19

Google also checked every other key in its root stores and said "no other keys included in our root stores share the same failure mode with weak entropy."

The CVEs

The CA's mistake isn't a software bug, so it doesn't get a CVE. Red Hat said it directly: "this is not a software vulnerability." Instead, projects assigned CVEs to their trust store updates so scanners and patch pipelines would pick them up.

CVECoversFixed in
CVE-2026-111943Go crypto/x509 denylist (GO-2026-6809); Red Hat's bulletin is filed under it tooGo 1.27.3, 1.26.10
CVE-2026-113470Firefox shipping the OneCRL block in-binary (MFSA 2026-111, reported by Wayne)Firefox 158.0.1, ESR 115.43.1, ESR 153.5.1
CVE-2026-114406RHEL ca-certificates changes (per Red Hat)Errata pending at time of writing
CVE-2026-91403Java (per Red Hat)See Java versions below
CVE-2026-113812Perl Mozilla::CA (per Red Hat)Mozilla::CA 20261020

The Go team's announcement was deliberately vague - "a small set of intermediate certificates due to specific security concerns" - because the bug wasn't public yet and the keys were trivial to recover. Go 1.25 and older get no fix: upgrade.

Patched versions

Compiled from Dennis Jackson's community tracker at emudhra.we-have-a-problem.com and vendor advisories, current as of October 22:

SoftwarePatched version
Go1.27.3, 1.26.10 (rebuild your binaries)
Node.js26.12.1, 24.22.1, 22.23.4
Python3.15.1, 3.14.9, 3.13.17
Python certifi2026.10.19
pip / uvpip 26.2.2, uv 0.13.4
Java (OpenJDK, Oracle JDK)27.0.1.0.2, 25.0.5.0.2, 21.0.13.0.2, 17.0.21.0.2, 11.0.33.0.2, 8u511
Rustwebpki-roots / webpki-root-certs 1.0.10, rustls-webpki 0.103.16
Bun / DenoBun 1.4.4, Deno 2.9.8
Electron44.9.1, 43.8.1, 42.11.16
NSS3.131.1
curl CA bundle2026-10-20
Composer ca-bundle1.6.0, 1.4.16
Homebrew ca-certificates2026-09-25_1
Debian ca-certificates20250419~deb12u2, 20250419+deb13u1 (DSA-6572-1), 20260816+nmu1
Ubuntu ca-certificates20260816ubuntu0.22.04.1 / 24.04.1 / 26.04.1 / 26.10.1 (USN-8944-1), older releases via USN-8944-2
Alpine ca-certificates20261020-r0
Arch ca-certificates-mozilla3.131.1-1
Fedora ca-certificates2026.2.92_v9.0.319
FreeBSD ca_root_nss1.131.1
Docker Desktop4.96.2
CloudflareWARP and 1.1.1.1 clients updated, cloudflared 2026.10.2
Red Hat Enterprise LinuxNo packages yet (RHSB-2026-012, rated Important) - use Red Hat's documented workaround

eMudhra's response

eMudhra revoked the eight certificates on October 18 - "within 14 hours of discovery," per its chairman - stopped issuance under the G3 root, and began migrating customers.

Its public position, from its status page: "No certificates had been issued from any of them, our infrastructure was not compromised, and no data was breached." It says the incident "does not affect its root CA private keys or its other intermediate CAs," and that its Indian DSC and eSign businesses run on completely separate infrastructure. It's offering every enterprise TLS customer certificates from an additional publicly trusted CA for redundancy, and CertiNext users can request Sectigo-issued certificates.

On October 22, eMudhra went further: eMudhra's board decided to "voluntarily withdraw from the global SSL/TLS certificate business." Chairman V. Srinivasan called it "the right decision for eMudhra and its shareholders," noting that global TLS is about 1% of revenue. The G1 RSA roots keep serving customers until the transition finishes, revocation services stay up until every certificate expires or is replaced, and affected customers get replacements "free of cost from partners." Its shares had fallen around 20% on October 21 alone, per Business Standard.

My read: the no issuance claim is backed by CT data. The no compromise claim is harder to accept at face value. Nobody needed to break in, because the keys could be calculated from public certificates. "Our infrastructure was not compromised" can be technically true and still miss the point. The Internet Freedom Foundation has formally asked eMudhra to explain that claim or correct it.

India's response

  • CERT-In issued advisory CIAD-2026-0050, "Compromise of eMudhra Intermediate CA Certificates," on October 21 (updated October 22). It says public disclosures "do not establish confirmed malicious exploitation of the affected keys," warns that the root removal can break legitimate certificates, and tells everyone: "Do not bypass certificate-validation warnings or disable certificate verification."
  • MeitY set up a special team to investigate on October 21. Officials said the impact on Indian sites "has been very limited and for a very short period."
  • The Internet Freedom Foundation wrote to eMudhra, CERT-In, MeitY and the CCA asking for a dated incident report, re-verification of all key ceremonies (including eMudhra's licensed Indian hierarchy), an independent audit, and clarity on when CERT-In was notified.

eMudhra Compromise Timeline

Date (UTC)Event
Apr 30, 2025Key ceremony creates 24 intermediates; P-384 keys for Series B and C are weak
May 2025Sectigo cross-signs all eight from AAA Certificate Services
May 29 - Jun 2025CRLs for the six TLS intermediates have invalid signatures (Bug 1970728); re-signed with the weak keys, bug closed
Oct 17, 2026, 18:05Wayne reports to Apple, Chrome, Microsoft, Mozilla, eMudhra
Oct 17, 19:45Chrome CRLSet blocks the six TLS intermediates
Oct 17, 22:59Firefox OneCRL block live
Oct 18, 09:24 - 09:38eMudhra revokes all eight (caCompromise); Mozilla opens restricted Bug 2083449
Oct 19Apple blocks; Sectigo revokes cross-signs; Android protected via Play Services; downstream trust stores notified
Oct 20Microsoft blocks; bug made public; Firefox 158.0.1 + ESRs; NSS 3.131.1 drops the G3 root; Go 1.27.3 / 1.26.10; Debian, Ubuntu, certifi, Composer and others ship
Oct 21Node.js 26.12.1 / 24.22.1 / 22.23.4; CERT-In CIAD-2026-0050; Red Hat RHSB-2026-012; eMudhra press release; MeitY team formed
Oct 22eMudhra announces exit from global SSL/TLS; Java patches listed; "No CT" test chains added to the checker
Oct 27Chrome Root Store removal of emSign ECC Root CA - G3 expected to reach devices

How to Protect Yourself: The Survival Guide

Browsers are handled. Your servers, scripts, containers and devices are not, until you update them.

Step 0: Test what you actually run

Don't test from your laptop's browser - it'll pass and tell you nothing. Run these from the same machine, container or runtime your application uses:

● ● ●BASH
# Does this client still trust the compromised intermediates?
curl https://dv-g3b-emudhra.we-have-a-problem.com/
curl https://dv-g3b-aaa-emudhra.we-have-a-problem.com/

# Does it also accept certs that were never logged to CT? (the silent-MITM case)
curl https://dv-g3b-noct-emudhra.we-have-a-problem.com/
curl https://dv-g3b-aaa-noct-emudhra.we-have-a-problem.com/

A certificate error is the result you want. A successful response means that client trusts the compromised keys. The -aaa- hosts test the Sectigo cross-sign path, which a lot of "I removed the emSign root" fixes miss.

Test your runtimes too, not just curl - they often use their own bundles:

● ● ●BASH
# Python (requests uses certifi, not the OS store)
python3 -c "import requests; requests.get('https://dv-g3b-aaa-emudhra.we-have-a-problem.com/'); print('STILL TRUSTS')"

# Node.js (bundled root store)
node -e "fetch('https://dv-g3b-aaa-emudhra.we-have-a-problem.com/').then(() => console.log('STILL TRUSTS'), e => console.log('blocked:', e.cause?.code))"
● ● ●POWERSHELL
# Windows trust store
Invoke-WebRequest https://dv-g3b-emudhra.we-have-a-problem.com/ -UseBasicParsing
Invoke-WebRequest https://dv-g3b-aaa-emudhra.we-have-a-problem.com/ -UseBasicParsing

Step 1: Update OS trust stores

● ● ●BASH
# Debian / Ubuntu
sudo apt update && sudo apt install --only-upgrade ca-certificates

# Fedora
sudo dnf upgrade ca-certificates

# Alpine
apk upgrade ca-certificates

# Arch
sudo pacman -Syu

# macOS (Homebrew-managed tools)
brew upgrade ca-certificates

RHEL: as of October 22 there's no fixed package yet. Red Hat's bulletin (RHSB-2026-012) points to a knowledge base workaround that distrusts both the emSign ECC Root CA - G3 and Comodo AAA Services roots - test it before rolling it out, since it can break legitimate chains under those roots.

macOS built-in tools: macOS itself blocks the intermediates, but the built-in curl, git, python3, perl, ruby and openssl verify against /etc/ssl/cert.pem without checking revocation, and Apple hasn't updated that file yet. The tracker site has a workaround; otherwise prefer Homebrew-managed binaries for anything security-sensitive until Apple ships an update.

Windows: Microsoft's block arrives through automatic certificate trust list updates. If you've disabled automatic root and disallowed-certificate updates via Group Policy (common on locked-down or air-gapped fleets), your machines didn't get it - deploy it yourself.

Step 2: Update runtimes that bring their own trust

This is where most teams get caught. Many runtimes ignore the OS trust store and ship their own snapshot.

RuntimeAction
GoUpgrade to 1.27.3 / 1.26.10 and rebuild every binary - the denylist is compiled in. A patched toolchain does nothing for binaries already deployed
Pythonpip install -U certifi (2026.10.19+), upgrade pip and uv; rebuild virtualenvs and lockfiles
Node.jsUpgrade to 26.12.1 / 24.22.1 / 22.23.4 - the bundled root store is a snapshot frozen at release time
JavaUpgrade to the patched JDK builds above. cacerts still trusts the AAA root, and JSSE doesn't check revocation by default
Rustcargo update -p webpki-roots (1.0.10+) and -p rustls-webpki (0.103.16+), then rebuild
Electron appsUpgrade Electron and ship a new app build to users
GraalVM native imagesRebuild - trust configuration is baked in at build time
Dart / FlutterCheck whether your app ships its own CA bundle; if so, update it

If you can't upgrade Java right away, you can block the 16 certificates directly by appending their SHA-256 fingerprints to $JAVA_HOME/lib/security/blocked.certs. That blocks only the compromised intermediates, with no collateral damage to the AAA or emSign roots. Here are the fingerprints, also useful as IOCs for any inventory or TLS inspection tool:

● ● ●TEXT
# eMudhra-signed intermediates (SHA-256)
42C4ACCD12C4F59597925E1A08A7A90102608543809308D50EC427E118BA1493  EM DV TLS CA - G3B
0164D7CEAE5BB909C272AF151FF44B1177AE9B47D9424B94F1D9558C30934D19  EM DV TLS CA - G3C
E7568FE6E12331F4FD7DE61DA4C7559D0F8EB192A218D4741A3BA75184333838  EM EV TLS CA - G3B
432EC25F0D28DE9006D97BF752F17BBB2CD41F669933FCB072D9A1148D0261F3  EM EV TLS CA - G3C
98B896625C0C230ADEEC3EB2CF6AAD5001ECF9156A68644E82374CE5833BC25B  EM OV TLS CA - G3B
CB6E15165AC802E9B3F993F16C25D41F4E81C21EBDE71AE1B012AC00BF9C7C3F  EM OV TLS CA - G3C
9E39DE2881273ACC225A149C72BA3E0F51424963669AB633EE1DC7DF5DB067B4  EM OV CS CA - G3B
4B2460A466F95FD40113BCDCCA2CEB29B3B093921DE45474DA7DF48874C630B1  EM OV CS CA - G3C

# Sectigo AAA Certificate Services cross-signs (SHA-256)
45A883F349AEDFD5F3A649B5498FFB121712BA8B448F3F2A91DBC5A766FCDDBE  EM DV TLS CA - G3B
62B7F9868263F72F6911FC78CEAF72C1979158B7368BF648683BB2AA39B02E72  EM DV TLS CA - G3C
579480AEA166290BD3C643589E795FC0D0E54E86505D180F1DFF99EFD3199512  EM EV TLS CA - G3B
FD9D5C2DBBD4995AB69B8D50C439D9527B00529199C2FD01B2174EB58F07021F  EM EV TLS CA - G3C
5F1DED4DD590AF74631290CF073B122A2AAC6A1FA479778A0BD43579BD832699  EM OV TLS CA - G3B
7485B51C0ED192878FA1D2F948FB529AE1842CC5086C4B67F7BE5B2039DE9489  EM OV TLS CA - G3C
A496E23AC0CAB8155FC9B117B97EAE368EFCBB9041AEC8804D5A308D2D01C2D8  EM OV CS CA - G3B
84112972B8E59D14560AE7E7119654474AAD119990CF3722BFC1E3B91615E1FD  EM OV CS CA - G3C

(blocked.certs takes just the hex fingerprints, one per line - drop the names.)

Step 3: Rebuild your containers

Your container images froze a trust store the day they were built. Updating the host does nothing for them.

● ● ●BASH
# Force fresh base layers and package updates
docker build --pull --no-cache -t your-app:latest .

Make sure your Dockerfile actually updates ca-certificates (or uses a base image released after October 20), and redeploy. Same goes for VM images, AMIs and golden images. If your base image vendor hasn't shipped yet, add an explicit ca-certificates upgrade step.

Step 4: If you own a site with an emSign certificate - migrate before October 27

This is the opposite problem: your legitimate certificate is about to stop working. Check what chain your servers present:

● ● ●BASH
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null 2>/dev/null \
  | grep -E '^ *[0-9]+ s:|^ *i:'

If you see emSign or EM ... CA - G3 anywhere in the issuer lines, get a new certificate from another CA hierarchy now. Google's guidance is blunt: operators "must immediately acquire and install a new TLS certificate from another PKI hierarchy included in the Chrome Root Store." If you're on ACME, point your client at a different CA and renew. eMudhra customers can reach out for free replacements.

Don't forget the places certificates hide: load balancers, CDNs, API gateways, mail servers, VPN concentrators, and anything with a manually uploaded cert.

Step 5: Hunt for forged code signatures (Windows fleets)

Since there's no CT log for code signing, you have to look yourself. With Microsoft Defender for Endpoint:

DeviceFileCertificateInfo
| where Timestamp > ago(30d)
| where Issuer has "EM OV CS CA"
| summarize Devices = dcount(DeviceId), Files = dcount(SHA1) by Issuer, Signer

Or locally with PowerShell:

● ● ●POWERSHELL
Get-ChildItem C:\ -Recurse -Include *.exe,*.dll,*.msi,*.ps1 -ErrorAction SilentlyContinue |
  Get-AuthenticodeSignature |
  Where-Object { $_.SignerCertificate.Issuer -match 'EM OV CS CA - G3' }

An empty result is what you want. Any hit deserves a hard look at the file, the device, and how it got there. If you're a software vendor that signed with an eMudhra code-signing cert, re-sign with a new CA and ship updated builds.

Step 6: Lock down mTLS endpoints

If any server validates client certificates against the public Web PKI trust store, it's in scope. Update that trust store too - it's often a different file from the one your outbound clients use. Better yet, mTLS should almost always use a private CA you control, not public roots.

Step 7: If you work in Indian fintech

eMudhra shows up across Indian fintech, so a few extra checks are worth doing:

  • eSign and DSC flows: eMudhra says its DSC and eSign services run on separate infrastructure under the Root Certifying Authority of India hierarchy, and CERT-In's advisory says the same. Nothing on the public record says otherwise, but so far this rests on eMudhra's own review. Watch for its root cause report and any CCA or MeitY findings.
  • Partner and vendor endpoints: run the openssl s_client check from Step 4 against every bank API, payment gateway, KYC provider and lending partner you call. If any of them serve an emSign G3 chain, your calls will start failing as your own clients get patched. Ask them to migrate now instead of loosening verification on your side.
  • Older Java services: a lot of banking and payments integration code runs on older JVMs with bundled cacerts. Patch the JDK or use the blocked.certs approach above.
  • Mobile apps: check whether your Android or iOS apps pin certificates or ship their own CA bundle, and whether any pinned chain involves emSign.
  • Reporting: if you find anything suspicious, such as a certificate chaining to one of these intermediates in your traffic, CERT-In's 2022 directions require reporting cyber incidents within six hours.

Do NOT "fix" errors by disabling validation

When the root removals land, some integrations will break - a vendor API with an emSign certificate, an internal tool, a partner endpoint. The temptation will be to make the error go away.

Don't.

Don't do thisWhy it's dangerous
curl -k / --insecureAccepts any certificate, including forged ones
requests.get(url, verify=False)Same, for every Python call that copies the snippet
NODE_TLS_REJECT_UNAUTHORIZED=0Disables verification for the entire Node process
InsecureSkipVerify: true (Go)Turns TLS into encryption-to-anyone
Trust-all TrustManager (Java)Same thing, in more lines of code
git config http.sslVerify falseYour source code is now MITM-able
Re-adding the removed emSign rootRe-opens exactly the hole that was closed

If a dependency breaks, the fix is for them to get a new certificate. In the meantime, if you absolutely must, pin the specific new chain or certificate for that one endpoint - never globally disable verification. CERT-In's advisory says the same: "Do not bypass certificate-validation warnings or disable certificate verification."

Why revocation alone isn't enough

"But eMudhra revoked the certificates on October 18. Isn't that the fix?"

For browsers, sort of - and only because browsers don't actually rely on live revocation checks. They use pushed blocklists (CRLSets, OneCRL, CRLite, Apple's and Microsoft's equivalents). For everything else, revocation is close to useless here:

  1. Most non-browser clients never check. By default, curl with OpenSSL, Go's crypto/x509, Python's ssl/requests, Node.js tls, Java JSSE and rustls do not check CRLs or OCSP. A revoked intermediate looks exactly like a valid one.
  2. Revocation is soft-fail. Clients that do check usually treat "couldn't reach the CRL/OCSP server" as "fine." An attacker who is already in a man-in-the-middle position can simply block that request.
  3. Revocation is per certificate, the compromise is per key. eMudhra's revocation covers eMudhra's certificates. The Sectigo cross-signs are separate certificates with the same keys - Sectigo had to revoke those separately, and a client would need to fetch AAA's CRL to see it.
  4. The keys are public forever. These keys can never be un-leaked. The only durable fix is a trust store that no longer trusts any path to them - which is why the real fix is root removal or key-level blocking, shipped as software updates.

That's why the long tail matters so much. Filippo Valsorda put it this way: "This will be a massive cleanup job, bigger than Heartbleed. There will be a very, very long tail." Appliances, IoT devices and forgotten internal tools with frozen trust stores will keep trusting these chains for years - and the emSign ECC Root CA - G3 certificate they trust is valid until 2043.

Long-term hardening

AreaActionWhy
Trust store inventoryList every trust store you run: OS, JVM, certifi, Node, Go binaries, containers, appliancesYou can't patch what you don't know exists
Patch pipelineTreat ca-certificates and runtime CA bundles as security updates with SLAsTrust store CVEs exist precisely so scanners catch them
Image hygieneRebuild container images on a schedule, not just on code changesOld images carry old trust
Use the OS storePrefer runtimes configured to use the system trust store (for example Node's --use-system-ca) where possibleOne place to patch instead of ten
CT monitoringMonitor CT logs for certificates issued for your domains (crt.sh, Cert Spotter, Facebook's CT monitor)Catches mis-issuance from any CA, including rogue ones
mTLSUse a private CA for client auth, never public rootsPublic CA compromise shouldn't grant access to your APIs
CAA recordsPublish CAA records for your domainsDoesn't stop a rogue key holder, but stops honest CAs from mis-issuing
CA vendor riskTrack your CA's Bugzilla compliance history before you buyeMudhra's 2025 CRL bug was public
Never disable validationLint for verify=False, InsecureSkipVerify, NODE_TLS_REJECT_UNAUTHORIZED in CITemporary hacks become permanent holes

The Bigger Picture

Let's zoom out. A few lessons here apply well beyond eMudhra.

1. Entropy failures are the scariest failures. Nobody had to break in. There was no malware, no insider, no phishing. The keys were wrong from birth, and math did the rest. Your HSM is only as good as the script that drives it and the human who picks the key label.

2. Certificate Transparency works. For browsers, CT turned a potential silent global MITM capability into something that would have been publicly logged and caught. Every non-browser client that doesn't enforce CT is living in the pre-2018 Web PKI.

3. Blocklists beat revocation. The browsers fixed this in hours because they push blocklists to clients. The rest of the ecosystem needed days of coordinated releases - and still has a long tail. If your software validates TLS, ask how it would receive an emergency distrust.

4. Block keys, not certificates. The cross-sign problem shows why key-based (SPKI) blocking is the right primitive. One key can live in many certificates.

5. Your trust graph is bigger than you think. As the Vercel breach showed with OAuth, your trust graph includes things you never chose. Most teams never picked eMudhra as a CA, yet every server they run trusted it. A single CA's mistake is everyone's problem.

6. Process signals matter. The invalid CRL signatures in 2025 were the moment this could have been caught. Treat cryptographic verification failures as incidents, not tickets.

What we still don't know: the full root cause (eMudhra's report is pending), how a FIPS 140-2 Level 3 HSM produced or accepted scalars below 256, and whether anyone exploited these keys against non-CT clients in the 17-month window. Chrome is also "closely investigating the ongoing inclusion of eMudhra's remaining CA certificates," so this story isn't over.


FAQ

What happened in the eMudhra CA key compromise?

Eight eMudhra (emSign) intermediate CA certificates, six for TLS and two for code signing, had P-384 private keys that were integers below 256. Anyone could calculate them from the public certificates. The keys came from an April 30, 2025 key ceremony and were reported on October 17, 2026.

Are eMudhra DSC and eSign services affected?

According to eMudhra and CERT-In, no. They run on separate infrastructure under the Root Certifying Authority of India hierarchy, while the compromised certificates belonged to eMudhra's global emSign TLS hierarchy. This is based on eMudhra's own review so far.

Do regular users need to do anything?

Keep your browser and operating system updated. Chrome, Firefox, Safari, Edge, Windows and Android already block the compromised certificates, usually without any action from you.

Were the compromised keys used in attacks?

There's no public evidence of misuse, and CERT-In says the disclosures "do not establish confirmed malicious exploitation." Browsers were protected by Certificate Transparency. For non-browser clients, nobody can prove the keys weren't used during the 17-month window.

What is CVE-2026-111943?

It's the CVE for Go's fix: Go 1.27.3 and 1.26.10 added a denylist to crypto/x509 that rejects chains containing the compromised intermediates. Red Hat's bulletin is also filed under it. Firefox's equivalent is CVE-2026-113470.

What happens to websites using emSign certificates?

Certificates chaining to emSign ECC Root CA - G3 stop being trusted by updated clients. Mozilla has already removed the root, and Chrome's removal reaches devices on October 27, 2026. Site owners need a replacement certificate from another CA hierarchy before then.


Conclusion

A key ceremony ran a test step. The test created a second set of keys. Someone picked the wrong key by its label. A CRL signature failed and got "fixed" with the wrong key. For seventeen and a half months, eight certificate authorities trusted by every major browser and OS were protected by keys you could guess in 255 tries.

One of them was 4.

The browsers were fine - thanks to Certificate Transparency and pushed blocklists, Chrome users were protected in 100 minutes. But everything else on the internet that speaks TLS - your API clients, your CI runners, your containers, your Java services, your IoT devices - is only as safe as the last time its trust store was updated.

For those of us in fintech, this is also a reminder to treat CAs as vendors with real risk. A trust provider you depend on for signatures and certificates can fail in ways nobody would have predicted.

Go update it. Then go check that it actually updated.


◆ KEY TAKEAWAY

Browsers were saved by Certificate Transparency and pushed blocklists; everything else depends on you. Test your actual runtimes against the -aaa- and -noct- endpoints, update OS trust stores, upgrade Go/Node/Python/Java/Rust and rebuild binaries and containers, migrate any emSign G3 certificates before October 27, and never "fix" a broken chain by disabling verification. Revocation doesn't save non-browser clients - only an updated trust store does.


References

© 2026 Dhruv VakharwalaNext.js · TypeScript · Tailwind · Cloudflare