Independent AI intelligence Two editions daily · ET
Fervor AI

Analysis · October 21, 2026 · concept

eMudhraagent-securityagent-infrastructureclaude-code

eMudhra's Certificate Keys Were the Number 4. Browsers Are Fixed. Your Scripts and Agents Need Six Fixes.

Browsers blocked the broken certificates in hours. The scripts, containers and coding agents on your machines trust a file on disk instead, and that file doesn't know.

A certificate authority's private key is supposed to be a number so large that nobody could guess it before the sun burns out. One of eMudhra's was 4.

That isn't a figure of speech. In a write-up published October 20, security researcher Scott Helme lists the private keys behind eight eMudhra intermediate certificates: 4, 56, 66, 115, 155, 156, 230 and 237. Keys like that take at most 255 guesses to find. He recovered all of them in under a second on a laptop.

Here's the part that matters for anyone who builds with code. Chrome and Firefox stopped trusting those certificates within hours of the report. But in Helme's tests, curl, Python and Node all accepted a forged certificate for api.stripe.com with default settings. The browser on your desk is safe. The script your agent just ran might not be.

The result is a split most teams haven't noticed: the internet's trust system got patched in two halves, and only one half patches itself.

What a certificate authority actually does

When your code connects to https://api.stripe.com, the server shows a certificate that says "I am api.stripe.com." Your code believes it because someone it already trusts signed that certificate. That someone is a certificate authority, or CA.

Think of it like a notary stamp. You don't know the person in front of you, but you know the notary, and the notary vouched for them. The stamp is only worth anything because nobody else can make it. A CA's private key is the stamp.

Most CAs sign through middlemen called intermediate certificates, which keeps the most valuable key (the root) locked away offline. eMudhra's eight broken keys belonged to intermediates: six for websites and two for code signing, created in April 2025, according to Helme.

Root, intermediate, then your site's certificate: that sequence is the certificate chain, and your code checks every link. If you hold an intermediate's private key, you can stamp a certificate for any domain you like. Google, your bank, your own API. Anything that trusts the chain will believe you.

According to Mozilla's incident bug, eMudhra blames a flawed key-generation script and human error. The root-cause investigation is still open.

Why browsers fixed it in hours

The report reached the browser makers on Saturday, October 17. Firefox blocked the certificates that night through OneCRL, its push list of revoked intermediates, per Mozilla's announcement, and Chrome did the same through its equivalent, CRLSets. eMudhra revoked the eight certificates the next day. Cloudflare's post on the incident describes the browser side as fixed "with a flip of a switch."

Browsers have three safety nets that most other software lacks:

  • A push channel. Chrome and Firefox can tell every copy of themselves, worldwide, "stop trusting this certificate," without a software update.
  • Certificate Transparency (CT). Chrome and Safari only accept certificates that appear in public logs. Helme notes that no TLS certificates chaining to these CAs showed up in CT, so a forged one would have been refused by default.
  • Revocation checks. A browser can ask whether a certificate was cancelled.

Your Python script has none of these.

Why everything else didn't

Outside the browser, most software trusts a CA bundle: a plain file on disk listing the roots it accepts. Python's requests reads one, Node ships one, Linux has the ca-certificates package, and Homebrew keeps its own. Helme's point is blunt. These clients trust the bundle, don't check revocation by default, and don't check CT. So the revocations that saved Firefox users do nothing for them.

He tested it. He set up a local server with a forged api.stripe.com certificate issued under one of the broken intermediates, then pointed tools at it:

  • curl printed "SSL certificate verify ok."
  • Python completed the handshake.
  • Node reported authorized: true.

He says this held on every Linux and macOS machine he tried. On Windows, CryptoAPI (the certificate-checking layer built into the OS) accepted the chain unless revocation checking was switched on.

That's every language most agent tooling is written in.

The cross-sign twist

You'd think the fix is simple: update the bundle and drop eMudhra's root. Mozilla did push an update on October 20 to NSS (its security library, whose root list many Linux distributions and tools like certifi copy) that removes the root behind these intermediates (emSign ECC Root CA - G3, per the Mozilla bug).

There's a catch. Each broken intermediate was also cross-signed by Sectigo's AAA Certificate Services root in May 2025. A cross-sign is a second notary vouching for the same middleman. So each key lives in two certificates, one per route, which is why Helme counts 16. And his forged-certificate test used the Sectigo route.

Sectigo has since revoked its cross-signed copies, per the Mozilla bug. But revocation only helps clients that check revocation, and we just covered who doesn't.

That's why Mozilla's guidance to everyone who builds on its trust store puts blocking the specific intermediates first, and treats removing the roots as the fallback. It's also why Go didn't wait for bundles at all. Go issue 82345, opened October 19 and closed October 20 as a release blocker, changes crypto/x509 so that verification "will now filter out chains which contain these intermediates," with backports to Go 1.26 and 1.27. Go hard-coded the bad keys into the language.

One insight to keep from all this: a trust store only knows what you've updated it to know, and a cross-signed certificate can walk around a root you removed.

Where agents come in

Coding agents make this worse in two quiet ways. (Neither is a bug in any particular agent. Both are habits.)

They run in old images. An agent working in a container uses whatever CA bundle was baked in when that image was built. If your base image predates this week, the agent's curl, pip and npm calls trust the broken chain no matter how current your laptop is.

They clear errors. When a TLS error appears, the fastest way to make it go away is curl -k, verify=False, or NODE_TLS_REJECT_UNAUTHORIZED=0. An agent told to "get the build working" can reach for exactly that. Cloudflare's own warning to developers this week was "not to resolve these errors by disabling verification." Some legitimate servers will start throwing those errors as root removals spread. Mozilla says the change will affect "the availability of some servers" for non-Firefox users until they move to new chains, and the Mozilla bug estimates about 30,000 eMudhra certificates need to migrate.

And one more thing. Helme added an update to his post: "Claude was able to recover the private keys with a single prompt." The math was never hard (a loop of 255 multiplications), but now it takes no math knowledge either. The person who forges a certificate with these keys doesn't need to know what an elliptic curve is.

Put this into practice

Here's the lowest-friction order. Most of it takes an afternoon.

1. Update every CA bundle you control. Helme's advice "boils down to 'update them.'" On Debian or Ubuntu machines and images:

sudo apt-get update && sudo apt-get install --only-upgrade ca-certificates

For Python projects that use certifi, pip install -U certifi. On a Mac with Homebrew, brew upgrade ca-certificates. Upgrade Node to its next release. Expect some of these to lag Mozilla's change by days, so check again next week. And a bundle update only removes roots; whether it closes every route depends on which roots your platform still trusts. That's why the Go fix below, which blocks the intermediates themselves, is the stronger kind.

2. Rebuild container images. Once your base images pick up the change, rebuild, and redeploy anything long-running. An updated laptop does nothing for a container built last month. If you run Cloudflare Tunnel, Cloudflare says to upgrade cloudflared to 2026.10.2 and redeploy container installs.

3. Upgrade Go services. Go's fix filters these chains in the standard library, which is stronger than a bundle update because it blocks the intermediates directly. The fix already shipped: Go 1.26.10 and Go 1.27.3, both dated October 19, include the crypto/x509 security fix. Upgrade to one of them or later, then rebuild and redeploy Go binaries (Terraform and kubectl are written in Go, Helme notes).

4. Find every place verification is turned off. Start with this rough search at the root of each repo:

grep -rnE "verify=False|curl -k|--insecure|NODE_TLS_REJECT_UNAUTHORIZED|InsecureSkipVerify" .

It's a first pass, not a full audit. It catches the common spellings and misses others (a config file setting, a library-specific flag, curl and -k on different lines), and some hits will be comments or test fixtures. Read every hit. Any real one is a spot where none of this week's fixes apply.

5. Give your agents a standing rule. Add one line to your CLAUDE.md, AGENTS.md, or whatever instruction file your agent reads:

Never disable TLS certificate verification (curl -k, verify=False,
NODE_TLS_REJECT_UNAUTHORIZED=0, InsecureSkipVerify). If a certificate
error appears, stop and report it.

That turns the most tempting shortcut into a question for a human.

6. If you bought certificates from eMudhra, check your own servers. See which chain they serve:

openssl s_client -connect yourdomain.com:443 -showcerts </dev/null | grep -iE "emsign|emudhra"

If you get hits, your certificate may need replacing as roots get removed. The Mozilla bug says eMudhra plans to move customers to chains under its emSign Root CA - G1.

Honest limitations

Some of this you can't fix. Helme says the intermediates don't expire until July 2039, and devices that never get a new CA bundle (old appliances, embedded boards, that one VM nobody owns) will trust them until then.

There's no sign anyone abused the keys yet. Cloudflare says its review found no active exploitation on its services, and Helme found no certificates from these CAs in CT logs. That's good news, but it's also the most that anyone can check from outside. A forged certificate used against a single non-browser client wouldn't show up anywhere public.

Bundle updates aren't instant, and I couldn't confirm which certifi or Node release carries the change at the time of writing. And blocking roots has a cost: some real servers will break before they migrate, which is exactly when someone reaches for -k.

What you do with this

The browser half of the internet patched itself while most people slept. The other half is scripts, containers, CI runners and agents, and it only changes when someone changes it.

You don't need to understand elliptic curves to act on this. You need one afternoon, the grep command above, and a line in your agent's instruction file. Start with the container your agents use most.

Sources: Scott Helme, "Eight bits of trust" (Oct 20, 2026); Cloudflare, eMudhra certificate compromise (Oct 20, 2026); Mozilla Bugzilla 2083449; Mozilla dev-security-policy announcement (Oct 20, 2026); Go issue 82345; Go release history. All read October 21, 2026.