The private key of a certificate authority β a chain of trust rooted in the Mozilla, Microsoft, Apple and Chrome root programs β is the number 4. Not a metaphor: the EC scalar is literally
4, on a P-384 curve where it should be a 384-bit random number. It has been recoverable from the public certificate since April 2025. I recovered it in 4 guesses and 2 milliseconds. And as of this morning, my Mac'scurlstill happily connects to servers impersonated with it.
The disclosure landed last week, the weaponization landed last night: mitmproxy now ships the actual compromised key behind a --emudhra flag, and CVE-2026-111943 got its number today. Browsers are safe. A very large amount of everything else is not β maybe including your terminal.
What happened
Eight eMudhra (emSign brand) intermediate CA certificates have incorrectly generated private keys β the top 376 bits of the P-384 scalars are all zeroes, leaving tiny integers you can brute-force from the certificate's public key alone. The intermediates chain to roots trusted by every major root program, and carry Sectigo cross-signs (through the old "AAA Certificate Services" root) as a second trust path. They were created in April 2025 with a validity stretching to 2040.
On Oct 17, a reporter known as Wayne reported it to the root programs with an undeniable proof: he signed the message "We have a problem here - Wayne" with each of the eight private keys.
- Oct 17: Firefox and Chrome block the intermediates
- Oct 19: Apple platforms block them; downstream trust stores notified
- Oct 20: Microsoft platforms block them; the disclosure site goes public
-
Oct 21, 23:51 UTC: mitmproxy merges
--emudhraβ the compromised key, shipping in a pentest tool - Oct 22, morning: CVE-2026-111943 is assigned
The CA has revoked the certificates, and browsers push the blocks through their fast revocation channels (OneCRL, CRLite, CRLSets). But revocation only protects clients that consume revocation information. That is a much shorter list than you'd hope.
Why your browser is fine (the trust fabric held β again)
Two independent systems saved the browsers:
- Certificate Transparency: these intermediates have zero CT log entries for their entire 18-month lifetime. CT-enforcing clients β Firefox, Chrome, Edge, Safari β could not have been attacked, because a leaf cert chaining through an unlogged intermediate is rejected outright. The attack surface never existed for them.
- Fast revocation: OneCRL / CRLite / CRLSets block the intermediates directly.
We keep arriving at the same conclusion: the web PKI survives its worst incidents not because CAs don't fail, but because the ecosystem around them assumes they will. (Same lesson as Let's Encrypt's multi-perspective validation β witnesses, not promises.)
Who is not fine
Everything that validates certificates without CT and without consuming revocation:
-
curl,wget,git(HTTPS remotes), package managers, CI/CD runners - Language runtimes with bundled trust stores: Go 1.27.3 / 1.26.10 fixed it, Node (22.23.4 / 24.22.1 / 26.12.1), Python certifi 2026.10.19, Rust rustls-webpki 0.103.16, Java, Deno, Electronβ¦ Claude Code shipped a fix (2.1.303) β your AI tooling's bundled roots were in the blast radius too. Bun and Erlang certifi are still "pending".
-
macOS is its own special case: the built-in
curl,git,python3,perl,rubyandopensslvalidate against/etc/ssl/cert.pemwithout checking revocation β and that file has not been updated.
I ran the disclosure's official self-check on my machine today:
$ curl https://dv-g3b-emudhra.we-have-a-problem.com/
Your client successfully connected to the site. That's bad!
$ curl https://dv-g3b-aaa-emudhra.we-have-a-problem.com/
Your client successfully connected to the site. That's bad!
Both trust paths β emSign root and the Sectigo/AAA cross-sign β still validate on stock macOS. The second server's certificate is issued by EM DV TLS CA - G3B, one of the eight compromised intermediates. My terminal accepted it. A "certificate error" would have meant I'm safe.
And the exposure is not theoretical: the disclosure's checker servers count every client that still connects successfully, per user-agent and JA4 fingerprint. There is live traffic. There are also live results.
Run it yourself: recover a CA private key from its public certificate
You need nothing but a public file. The certificates are in the disclosure's proof.zip (and impacted-intermediates.json lists all eight). Then:
# recover.py β the private key from the public certificate alone
import sys
from cryptography import x509
from cryptography.hazmat.primitives.asymmetric.ec import derive_private_key
cert = x509.load_pem_x509_certificate(open(sys.argv[1], "rb").read())
pub = cert.public_key().public_numbers()
for d in range(1, 1_000_000):
if derive_private_key(d, cert.public_key().curve).public_key().public_numbers() == pub:
print(f"private key recovered: d = {d}")
break
Real run, on the EM OV TLS CA - G3C intermediate:
$ python3 recover.py EM-OV-TLS-CA-G3C.crt.pem
private key recovered: d = 4
Four guesses. Two milliseconds. From 1,240 bytes of fully public data. A CA private key that should take longer than the age of the universe to brute-force fell to a loop that didn't even reach its first coffee. The verification is one command away, and Wayne's proof ships exactly that way:
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
Then the weaponization, for the lab only: mitmproxy --emudhra makes the proxy sign interception certificates with the real compromised key, so any client that still trusts the chain β say, a stock macOS curl β accepts an impersonated site without a single warning. One flag. That's how undramatic this failure is to exploit.
The fix
-
Patch the trust stores β the disclosure maintains the exact list. Headlines: Ubuntu/Debian/Alpine/Fedora/Arch
ca-certificates(all shipped this week), Go 1.27.3 / 1.26.10, Node 22.23.4+, Python certifi 2026.10.19 (thenpip install -U certifi), Rust rustls-webpki 0.103.16, Deno 2.9.8, Docker Desktop 4.96.2, Claude Code 2.1.303, curl CA bundle 2026-10-20. - macOS, today, without waiting: strip the two affected roots from the file the built-in tools actually read (official workaround):
sudo cp -p /etc/ssl/cert.pem /etc/ssl/cert.pem.bak &&
sudo awk '/^(###|===) /{skip=0}
/^=== .*\/CN=(AAA Certificate Services|emSign ECC Root CA - G3)$/{skip=1}
!skip' /etc/ssl/cert.pem.bak | sudo tee /etc/ssl/cert.pem > /dev/null
Then re-run the two curl self-checks. "Certificate error" is the sound of being safe.
-
Linux servers: the disclosure ships
sed-based workarounds for Debian/Ubuntu, Alpine, Fedora/RHEL-family, Arch, NixOS β they distrustemSign ECC Root CA - G3andComodo AAA Services rootuntil the distro'sca-certificatesupdate lands. The cross-sign path is the one people forget: blocking only the emSign root leaves the AAA path wide open β my secondcurlproved exactly that. -
Offline Windows machines: Microsoft ships the block through automatic trust-list updates; air-gapped fleets need the
Block-EmudhraCompromisedCA.ps1script (16 intermediates and cross-signs into the Disallowed store).
The nuance worth keeping
Your microcontroller probably escaped. Embedded devices don't ship 150-root bundles β they pin one root per connection, so the compromised chain simply isn't in their firmware. The flip side is scarier: those bundles are frozen until 2039. The next mis-generated CA whose root is pinned in firmware will have no such luck. The real exposure was never the constrained devices β it's the desktops, the CI runners, and everything written in Go.
TL;DR
A trusted CA shipped eight private keys that were guessable small integers, and they sat in the wild for 18 months. Browsers were saved by Certificate Transparency β again. Your terminal tools were not: check with the two curl one-liners, patch your trust stores, and on macOS apply the cert.pem workaround today. And if you want to feel it viscerally: recover the key yourself β it's four guesses.
Sources: official disclosure + self-checks + patched list Β· Mozilla bug tracker incident report Β· MCU analysis β Daniel Mangum Β· mitmproxy --emudhra commit Β· CVE-2026-111943












