Eight CA keys, and every one of them was smaller than 256
At 16:27 UTC on 17 October, a researcher who signs his reports "Wayne" ran a script over the CCADB and got a hit he did not expect. Eight intermediate CAs run by eMudhra had P-384 keys that fell over almost instantly. P-384 is fine. The private keys were tiny integers. Mozilla's Dennis Jackson put it bluntly in the Bugzilla incident: all eight "used integers less than 256." Generate the first 256 P-384 keys, compare, done. The Register reports that one of them was literally the number 4.
Six of those intermediates were TLS CAs trusted by Chrome, Mozilla, Apple and Microsoft. The other two were code-signing CAs trusted by Microsoft. Whoever holds those keys can sign a certificate for any hostname, and by now that's anyone who can read a bug tracker.
Browsers sorted it out in an evening. Your stack is another story. I ran a check from a Debian 12 container this morning and it still trusts a forged chain.
Browsers were done before dinner
Here's the timeline from the Bugzilla thread and Google's write-up, all times UTC:
- 17 Oct, 18:05: report emailed to Apple, Chrome, Microsoft, Mozilla and eMudhra
- 17 Oct, 19:45: Chrome ships a CRLSet blocking the six TLS intermediates by SPKI hash
- 17 Oct, 22:59: Mozilla finishes blocking all eight through OneCRL
- 18 Oct, 09:24 to 09:38: eMudhra revokes the eight certificates, reason
cACompromise - 19 Oct: Sectigo revokes its cross-signs of the same keys, Apple blocks the CAs, and Android gets the Chrome-equivalent update through Google Play Services around 22:00
- 20 Oct: Microsoft blocks them, Mozilla announces an emergency removal of the whole
emSign ECC Root CA - G3root, and Chrome commits to the same
One date doesn't line up: eMudhra's own statement says the report arrived on 18 October. The reporter and Mozilla both say 17 October, with timestamps. I'm going with them.
What saved browser users was CT. Google says no TLS certificate chaining to these six intermediates was logged to Certificate Transparency before the CRLSet went out, and the CT logs now reject them. Chrome, Firefox, Safari and Edge refuse certificates that aren't logged. So nobody could have used a forged one against a browser, at any point since the keys were generated in April 2025.
Good for CT. It only protects clients that enforce it, though.
Your curl doesn't read CRLSets
curl, Python requests, Java's HTTP clients, Go's net/http, Node's fetch, anything linked against OpenSSL with default settings: none of them enforce CT, and none of them fetch CRLs or OCSP unless you go out of your way. CRLSets and OneCRL live inside the browser. The long version is in what actually happens when you revoke a certificate and how CRLite changed Firefox.
A non-browser client decides trust from a file. If emSign ECC Root CA - G3 is in that file, a certificate signed by one of the eight keys verifies. Revoked or not.
The second path is nastier. Sectigo had cross-signed the same keys under AAA Certificate Services, the old Comodo root. Sectigo says in the bug that this root left the Chrome and Mozilla stores some time ago. Microsoft and Apple still trust it, and so do plenty of Linux bundles. My Debian 12 container, on ca-certificates 20250419~deb12u1, has both roots:
openssl crl2pkcs7 -nocrl -certfile /etc/ssl/certs/ca-certificates.crt \
| openssl pkcs7 -print_certs -noout \
| grep -E 'subject=.*(emSign ECC Root CA - G3|AAA Certificate Services)'
Two lines of output means you're exposed on both paths.
And your CT monitor won't catch it. Someone going after your API clients has no reason to log the forged certificate, because those clients never ask. CT monitoring catches CAs making mistakes in public. A leaked key used against a client that ignores CT is invisible to it.
Test the clients, skip the changelog
In the bug, Mozilla's Dennis Jackson points people to a checker site that serves leaf certificates signed with the compromised keys. Two of its hosts cover both paths. One chains straight to the emSign root, the other goes through the Sectigo cross-sign. You want a certificate error.
curl -sS -o /dev/null https://dv-g3b-emudhra.we-have-a-problem.com/ && echo "STILL TRUSTED (emSign path)"
curl -sS -o /dev/null https://dv-g3b-aaa-emudhra.we-have-a-problem.com/ && echo "STILL TRUSTED (Sectigo cross-sign path)"
From my unpatched Debian 12 container, both returned HTTP 200. Node 24.21.0 in the same container trusted the direct path and rejected the cross-sign, because Node bundles its own Mozilla-derived roots and those don't include the AAA root. Same box, two answers. That's why trust stores in containers never behave the way you assume.
Run those two lines from every runtime you deploy. Your laptop proves nothing.
Container images
Patching the host does nothing for your containers. Every image carries its own bundle, frozen at build time. You can pull it out without a shell in the image, so this works on distroless too:
cid=$(docker create your-registry/api:prod)
docker cp "$cid":/etc/ssl/certs/ca-certificates.crt ./bundle.pem
docker rm "$cid" >/dev/null
openssl crl2pkcs7 -nocrl -certfile bundle.pem | openssl pkcs7 -print_certs -noout \
| grep -cE 'emSign ECC Root CA - G3|AAA Certificate Services'
Anything above zero means rebuild. Debian's 20260816+nmu1 upload to unstable on 20 October blocklists both "emSign ECC Root CA - G3" and "Comodo AAA Services root", according to its changelog. The checker's table lists 20250419~deb12u2 for bookworm, plus fixed versions for Ubuntu, Alpine, Fedora and Chainguard. An image built last week from debian:12 has none of that.
Go binaries
Go is the odd one out, in a good way. Go 1.27.3 and 1.26.10 hardcode the SHA-256 SPKI hashes of all eight intermediates in crypto/x509 and reject any chain that contains one (CVE-2026-111943). The diff patches the macOS and Windows verifier paths too, so the block holds whatever system store sits underneath. The HN thread argued about whether a compiler should be doing root-program work. Fair question, but it's the only runtime here that didn't wait on a bundle.
The catch is that the fix lives in the binary. Every statically linked tool you didn't build yourself keeps the Go it was compiled with.
go version /usr/local/bin/* 2>/dev/null | grep -vE 'go1\.(27\.([3-9]|[1-9][0-9])|26\.([1-9][0-9]))'
Anything that prints predates the fix. Our Go 1.27 GODEBUG post covers finding them.
Python, and the certifi release to skip
Requests uses certifi, which ignores the system store. certifi 2026.10.18 pulled all four emSign roots, including emSign Root CA - G1, which Mozilla is explicitly not distrusting. About a day and a half later, 2026.10.19 put G1, C1 and C3 back and left only G3 out. This matters because eMudhra is moving its affected customers onto G1 chains. Pin 2026.10.18 and you'll reject those sites once they migrate. Use 2026.10.19 or later.
python3 -c "import certifi; print(certifi.__version__, certifi.where())"
Java and macOS
Java reads its own cacerts, and revocation checking is off by default. The checker lists patched builds for 8, 11, 17, 21, 25 and 27. Go by your vendor's release notes. Grepping the keystore can mislead you, because a patched JDK can block the intermediates and still keep the root alias. On macOS the system frameworks were patched on the 19th, but the bundled command-line curl, git, python3 and openssl verify against /etc/ssl/cert.pem without checking revocation, and the checker says that file hasn't been updated.
eMudhra customers have until 27 October
Now the sites that bought from eMudhra. Chrome removes emSign ECC Root CA - G3 from the Chrome Root Store on the morning of Tuesday 27 October, Pacific time, and earlier on Canary and Beta. Google's advice to site operators is one sentence: "immediately acquire and install a new TLS certificate from another PKI hierarchy."
eMudhra told Bugzilla on 20 October that about 30,000 certificates need to move, and about 97% of them were issued over ACME. It has stopped issuing from every intermediate under that root and is migrating subscribers to its RSA root, emSign Root CA - G1.
Check whether you're one of them before Chrome tells you:
host=shop.example.com
openssl s_client -connect "$host:443" -servername "$host" -showcerts </dev/null 2>/dev/null \
| grep -E '^ *[0-9]+ s:|^ +i:' | grep -iE 'emudhra|emsign'
If that prints anything, follow the i: lines to the top of the chain. If it ends at emSign ECC Root CA - G3, you need a new certificate this week. Since nearly all of these came through ACME, the fix for most people is a new directory URL and a forced renewal. No procurement ticket. My advice: switch CAs. I wouldn't wait for a G1 reissue from the same one. It's the same drill as the HARICA and SSL.com revocations earlier this month, with a longer fuse. And if your ACME client can only talk to one CA, that's single-CA risk coming due.
An audited HSM ceremony made keys a laptop could guess
The cause is still coming out. eMudhra says the eight keys came from a key generation ceremony on 30 April 2025. A key wrap/unwrap step being tested that day "produced a second, weak set of keys alongside the original strong keys," and the weak set ended up in the certificates. eMudhra says the ceremony ran on Utimaco HSMs and that the hierarchy later passed two independent audits.
Commenters in the bug want to know how a FIPS-validated HSM produces a P-384 scalar under 256 unless somebody fed it one. No answer yet.
There was a warning, too. In May 2025 eMudhra published CRLs for the same six TLS intermediates with invalid signatures, filed as Bug 1970728. A CRL that won't verify against its issuer's public key is what you'd expect if the signing key isn't the key in the certificate. Seventeen months, nobody connected it.
Our post on the 512-bit CA key that fell in 32 hours was about key size. P-384 is big enough. The algorithm on the certificate says nothing about the key you actually got, and your internal CA could have the same bug without any audit noticing.
Put the trust bundle in your inventory
Every team I've worked with tracks its certificates, mostly badly. Almost nobody tracks the trust stores that decide which certificates their own software accepts. Those got patched this week in dozens of places, and your fleet only picks them up when something gets rebuilt.
So list them next to the certificates: base image, ca-certificates version, Go toolchain, certifi, JDK build. Rebuild images on a schedule, even when the app hasn't changed. Run the two curl probes from inside the containers that matter for the next few weeks. If there's no inventory yet, start by counting your certificates. Then count the bundles.
Chrome and Firefox fixed this within five hours of the report. Your rebuild is the only thing between your services and anyone who can count to 256.
Frequently asked questions
Were any websites actually attacked with the compromised eMudhra keys? There are no confirmed reports. Google says no certificate chaining to the six TLS intermediates was logged to CT before Chrome blocked them, so CT-enforcing browsers could not have been attacked. Nobody can say the same for non-browser clients, because a forged certificate used against them never has to show up anywhere public.
Does updating the host operating system protect my Docker containers?
No. Each image carries the CA bundle it was built with, so you have to rebuild on a patched base image and redeploy. Copy the bundle out with docker cp and check it for the emSign ECC Root CA - G3 and AAA Certificate Services roots.
Is emSign Root CA - G1 being distrusted as well? Not right now. Mozilla said on 20 October that it is not removing trust in emSign Root CA - G1, and eMudhra is moving affected customers onto it. The Chrome Root Program says it will look into the inclusion of eMudhra's remaining CA certificates, so read the Bugzilla incident before you build anything new on that hierarchy.
Why not just turn on revocation checking in my HTTP clients? The eight intermediates are on eMudhra's and Sectigo's CRLs, but soft-fail revocation checking breaks down exactly when an attacker controls the network. Removing the root or blocklisting the keys works offline and can't be dodged by blocking a CRL download, which is why most trust store maintainers went that way.
How long do I have if my certificates chain to emSign ECC Root CA - G3? Chrome removes the root on the morning of 27 October 2026, Pacific time, and Mozilla announced its emergency removal on 20 October. Replace the certificate this week with one from a different CA hierarchy.