Eight eMudhra intermediate CA certificates were issued with private keys generated from single- or double-digit values — one key was literally the number 4 — making them trivially recoverable from the public certificates. Browsers and OSes blocked them October 17–20; Chrome removes the emSign ECC Root CA – G3 root entirely on the morning of October 27 (PT). Go tracks the trust-handling fix as CVE-2026-111943. eMudhra announced its exit from the global SSL/TLS business on October 22.
Verdict: not an attack — an operational deadline. No malicious use of the weak keys has been observed (Talos), so the work is certificate inventory and replacement, not hunting. The real event is October 27: when Chrome drops the G3 root, legitimate certificates chaining to it stop working, and clients with independent trust stores (VPNs, proxies, CI/CD tooling, appliances, embedded devices) stay silently trusting the compromised intermediates until someone updates them. Expect PKIX/TLS failures to surface as "mystery outages" — have the answer ready before the tickets arrive.
The eight intermediates (six TLS, two code signing) were issued in April 2025 with P-384 private keys generated from values below 256 — anyone can recover them and forge trusted certificates or sign code. eMudhra revoked the certificates; Chrome, Firefox, Apple and Microsoft blocked them Oct 17–20; Mozilla removed the root Oct 20; Google removes the root from the Chrome Root Store Oct 27 and is reviewing eMudhra's remaining roots. The attack risk is real but theoretical so far; the availability risk is scheduled.
| Category | Source | Status |
|---|---|---|
| Vendor | eMudhra | Exiting the business — Oct 22 press release: voluntary withdrawal from global SSL/TLS (~1% of revenue). Operationally useful: affected certificates replaced free of cost through partners; revocation/status services run until every issued cert expires or is replaced; G1 RSA roots keep serving during the transition. Vendor's own claims (not independently verified): CAs revoked within 14 hours, no end-entity certs issued from the affected CAs, infrastructure not compromised; full root-cause report promised to browser root programs. Incident detail: vendor incident post |
| Network IDS | Cisco Talos | Snort SIDs 67363–67374 published for coverage of the compromised intermediates (tier A) |
| Indicators | Talos / trackers | Published — SHA-256 hashes of all eight certificates, on the IoC card; usable for trust-store and inventory sweeps |
| Trust stores | Chrome / Firefox / Apple / Microsoft / Go (vendor post) | Enforced — Chrome, Firefox and Apple block the six TLS intermediates; Microsoft blocks the two code-signing intermediates; Chrome root removal lands Oct 27. Go 1.27.3 / 1.26.10 filter chains by the eight SPKI SHA-256 hashes (different values than the cert hashes — see Go release notes) |
| VM scanners | Qualys / Tenable / Rapid7 | Nothing specific published — the practical check is certificate inventory (CT logs, config management, TLS scans), not a CVE scan |
| Hunting | — | Nothing to hunt — no abuse observed; escalation triggers below cover the reversal |
No scanner content exists because this is a trust problem, not a CVE scan. Everything below is doable today with standard tooling:
Spot-check any endpoint's chain — one-liner per host:
openssl s_client -connect host:443 -showcerts </dev/null 2>/dev/null \ | openssl x509 -noout -issuer # flag any issuer containing "emSign" or "eMudhra"
Estate-wide inventory — if you run TLS inspection or Zeek, the data already exists:
# Zeek x509.log / TLS-inspection metadata
certificate.issuer contains ("emSign" OR "eMudhra")
→ before Oct 27: that's the replacement worklist
→ after Oct 27: a NEW cert chaining to the weak intermediates = forgery, escalate
Exact-match sweep — the eight compromised intermediates by hash:
compare observed intermediate cert SHA-256 against the eight published hashes (on the IoC card) in proxy/Zeek logs and local trust stores # also: flag code signed by the two code-signing intermediates
Splunk (index=*) / Elastic ES|QL (FROM logs-*) — CIM Certificates field names for Splunk, ECS tls.server.* for Elastic (Zeek x509/ssl, TLS-inspection, Packetbeat); tune to your add-on or integration:
# estate-wide issuer sweep: before Oct 27 this is the replacement worklist
index=* earliest=-30d@d (ssl_issuer="*emSign*" OR ssl_issuer="*eMudhra*" OR issuer="*emSign*" OR issuer="*eMudhra*" OR certificate.issuer="*emSign*")
| eval issuer=coalesce(ssl_issuer, issuer, 'certificate.issuer')
| stats dc(dest) as servers values(dest) as hosts values(ssl_subject) as subjects by issuer
# exact-match sweep: the eight weak-key intermediates by SHA-256 (values on the IoC card)
index=* earliest=-30d@d (ssl_hash IN ("<eight SHA-256 from the IoC card>") OR certificate.hash IN ("<same>"))
| stats count values(dest) as hosts min(_time) as first by ssl_hash
# after Oct 27: any NEW certificate chaining to the weak intermediates is forgery, escalate
index=* earliest=-1d@d ssl_issuer IN ("*emSign*","*eMudhra*")
| stats min(_time) as first_seen by ssl_subject ssl_serial
| where first_seen > relative_time(now(), "-1d@d")
// estate-wide issuer sweep: before Oct 27 this is the replacement worklist
FROM logs-*
| WHERE @timestamp > NOW() - 30 days
| WHERE tls.server.x509.issuer.distinguished_name LIKE "*emSign*" OR tls.server.x509.issuer.distinguished_name LIKE "*eMudhra*"
OR tls.server.issuer LIKE "*emSign*" OR tls.server.issuer LIKE "*eMudhra*"
| EVAL issuer = COALESCE(tls.server.x509.issuer.distinguished_name, tls.server.issuer)
| STATS servers = COUNT_DISTINCT(destination.ip), hosts = VALUES(destination.ip), subjects = VALUES(tls.server.subject) BY issuer
// exact-match sweep: the eight weak-key intermediates by SHA-256 (values on the IoC card)
FROM logs-*
| WHERE @timestamp > NOW() - 30 days
| WHERE tls.server.hash.sha256 IN ("<eight SHA-256 from the IoC card>")
| STATS count = COUNT(*), hosts = VALUES(destination.ip), first = MIN(@timestamp) BY tls.server.hash.sha256
// after Oct 27: any NEW certificate chaining to the weak intermediates is forgery, escalate
FROM logs-*
| WHERE @timestamp >= DATE_TRUNC(1 day, NOW() - 1 day)
| WHERE tls.server.issuer LIKE "*emSign*" OR tls.server.issuer LIKE "*eMudhra*"
| STATS first_seen = MIN(@timestamp) BY tls.server.subject, tls.server.x509.serial_number
| SORT first_seen DESC
eMudhra — incident post (vendor) · eMudhra — exit press release, Oct 22 (vendor) · Cisco Talos — compromised intermediates · BleepingComputer — browser blocks · The Hacker News — eMudhra exits TLS · TNW — "one key was the number 4" · CertKit — distrust mechanics