Like discovering your building's master key is just the number 4 — and the locksmith handed it out 17 months ago
CVE-2026-114820 addresses the removal of eMudhra (emSign) root CA certificates from the Java SE trust store. Eight intermediate CA certificates issued by eMudhra in April 2025 were generated with catastrophically weak P-384 private keys — 8-bit scalars (literal values 4, 56, 66, 115, 155, 156, 230, 237) instead of proper 384-bit random numbers. Anyone can recover these keys by testing 256 integers in under a second. Six intermediates sign TLS certificates; two sign code. Each exists in dual form: signed by eMudhra's emSign ECC Root CA - G3 root and cross-signed by Sectigo's legacy AAA Certificate Services root — 16 compromised certificates total. Every Java SE version from 8u511 through 27.0.1 (including GraalVM variants) ships with these roots trusted in cacerts. Because JSSE disables OCSP/CRL checking by default and lacks Certificate Transparency enforcement, even the Oct 18 revocations by eMudhra and Sectigo are invisible to unpatched JVMs. An attacker who recovers a key can forge a valid TLS certificate for *any domain* and present it to any Java application.
Oracle rates this CVSS 9.1 CRITICAL, and the score is accurate. Unlike browsers — which deployed OneCRL/CRLSets blocks within hours on Oct 17 — Java relies on static bundled trust stores with no push-based revocation. The 9.1 reflects AV:N/AC:L/PR:N/UI:N with high confidentiality and integrity impact. The only reason it isn't 10.0 is the absence of availability impact (the attacker reads and modifies data but doesn't crash the JVM). Oracle's first Security Alert (CVE-2026-91403 on Oct 21) added the 16 intermediates to blocked.certs; this second alert (CVE-2026-114820 on Oct 24) goes further and removes the eMudhra root CAs entirely. Both steps are needed — the block list is a targeted scalpel, the root removal eliminates the trust anchor permanently.
5 steps from start to impact.
Recover compromised intermediate CA private keys
crt.sh. Using standard ECC scalar multiplication against the NIST P-384 base point, they brute-force integers 1–255 and compare against the certificate's public key. All 8 keys are recovered in under one second on commodity hardware. Scott Helme demonstrated this on a laptop.- Public access to CT logs or any certificate chain containing the intermediates
- None — the math is trivial and the certificates are public
Forge a TLS certificate for the target domain
EM DV TLS CA - G3B with d=4), the attacker generates a Certificate Signing Request for the victim's FQDN (e.g., api.target.com) and signs it. The resulting certificate chains to either emSign ECC Root CA - G3 or AAA Certificate Services — both trusted by default in Java's cacerts. The forged certificate is indistinguishable from a legitimate one to any JSSE client.- Recovered private key from Step 1
- Knowledge of target domain name
- None — standard OpenSSL commands suffice:
openssl req -new -key recovered.key -subj '/CN=api.target.com' | openssl x509 -req -CA intermediate.pem -CAkey recovered.key
crt.sh, Censys) would log a misissued certificate if the attacker submits SCTs, but CT submission is optional and Java does not enforce CT.Establish network interposition
- Network proximity or infrastructure-level access to redirect traffic
- Enterprise internal networks with proper segmentation, 802.1X, and DNSSEC reduce exposure
- Internet-facing Java clients (CI/CD pulling from Maven Central, API gateways) are more exposed
Present forged certificate to Java JSSE client
cacerts. OCSP/CRL checking is disabled by default (com.sun.net.ssl.checkRevocation=false), and Java has no Certificate Transparency enforcement. The handshake succeeds. The attacker now holds both ends of the TLS session.- Victim JVM running any affected Java version (8u511 through 27.0.1) with default JSSE configuration
- Network interposition from Step 3
- Applications with custom
TrustManagerimplementations or certificate pinning would reject the forged cert - Applications explicitly enabling revocation checking (
-Dcom.sun.net.ssl.checkRevocation=true) would reject revoked intermediates — but this is rare in production
javax.net.debug=ssl is enabled, but this is almost never on in production.Intercept, exfiltrate, or modify application data
- Successful MITM from Steps 3-4
- Application-layer integrity checks (e.g., Maven artifact SHA verification, GPG signature checks) would detect tampered dependencies — but many builds skip these
- mTLS (mutual TLS) with client certificates adds a second authentication factor the attacker cannot forge
javax.net.debug logging, which is typically off.keytool -delete -keystore $JAVA_HOME/lib/security/cacerts -storepass changeit -alias emsigneccrootcag3 (repeat for emsignrootcag1 and emsignrootcag2). This severs the trust chain at the root, making it impossible for JSSE to validate any certificate chaining to eMudhra roots — including both the direct eMudhra-signed and Sectigo-cross-signed paths (since the Sectigo path is handled by the blocked.certs intermediate block). Inventory ALL cacerts files across every JDK/JRE installation, including embedded JREs in application servers, Docker images, and GraalVM native-image builds (which must be recompiled). Restart all JVM processes after modification. Per the noisgate mitigation SLA for CRITICAL, deploy within 3 days.$JAVA_HOME/lib/security/blocked.certs. This is what Oracle's CVE-2026-91403 patch does. The blocked intermediates are rejected during PKIX path validation regardless of the root trust status. Download the fingerprint list from the OpenJDK changeset JDK-8395142. Per the noisgate mitigation SLA for CRITICAL, deploy within 3 days.-Dcom.sun.net.ssl.checkRevocation=true -Dcom.sun.security.enableCRLDP=true. eMudhra and Sectigo revoked all 16 intermediates on Oct 18, 2026, so OCSP/CRL checks will reject them. This adds 50-200ms latency to TLS handshakes (CRL fetch) and depends on network reachability to revocation endpoints. Not a substitute for root removal or blocked.certs — treat as a bridge until the definitive fix is deployed. Set via JAVA_TOOL_OPTIONS env var for fleet-wide application without code changes.TrustManager or application-level certificate pinning to accept only known leaf or intermediate certificate fingerprints. This defeats forged certificates regardless of CA trust status. Maintenance-intensive — pin rotation requires coordinated updates. Use as defense-in-depth alongside root removal, not as a standalone control.- Network IDS/IPS — Cannot detect MITM attacks using cryptographically valid (though fraudulently issued) TLS certificates. The forged cert passes all standard validation checks.
- Web Application Firewalls — WAFs protect *inbound* HTTP traffic. CVE-2026-114820 is an *outbound* TLS trust issue affecting the Java application as a client, not as a server.
- Standard EDR — Does not inspect JVM-internal certificate chain validation. The TLS handshake occurs inside the Java process; EDR sees only encrypted network traffic.
- Upgrading only to the CVE-2026-91403 patched builds (.0.2) — These add intermediates to
blocked.certsbut leave eMudhra root CAs incacerts. CVE-2026-114820 specifically addresses root removal. Both fixes are needed for complete remediation. - Enabling
javax.net.ssl.trustStoreoverride without modifying it — Pointing JSSE to a custom trust store that still contains emSign roots does not help. The custom store must also have the roots removed.
The supporting signals.
| In-the-wild exploitation | No confirmed exploitation. eMudhra states no evidence of key recovery or abuse before Oct 17 disclosure. Not in CISA KEV. However, the weak keys were publicly derivable for 17 months (April 2025 → October 2026) — passive exploitation by a sophisticated adversary cannot be ruled out. |
|---|---|
| Proof of concept | No traditional PoC exploit needed. The 'exploit' is recovering P-384 private keys by brute-forcing integers 1–255 — any ECC library suffices. Scott Helme recovered all 8 keys on a laptop in <1 second. Test domains at *.we-have-a-problem.com (e.g., dv-g3b-emudhra.we-have-a-problem.com) allow verification. Mark Struberg's CheckCompromisedCa.java tests trust chain acceptance. No dedicated GitHub CVE-named exploit repos found on pocindex.io. |
| EPSS | Not yet scored — CVE-2026-114820 was disclosed Oct 24, 2026 (1 day ago). FIRST EPSS requires ~30 days of data. Score expected to be moderate since exploitation requires network interposition rather than a traditional remote code execution vector. |
| KEV status | Not listed in CISA Known Exploited Vulnerabilities catalog as of Oct 25, 2026. Companion CVE-2026-91403 also not listed. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N — Network-accessible, low complexity, no authentication, no user interaction. High confidentiality + integrity impact (read *and* modify all data). No availability impact. The AC:L is justified because the cryptographic failure makes certificate forging trivial; the MITM requirement is a deployment condition, not attack complexity per Oracle's scoring methodology. |
| Affected versions | Oracle Java SE: 8u511-b32, 8u511-perf-b32, 11.0.33.0.2, 17.0.21.0.2, 21.0.13.0.2, 25.0.5.0.2, 27.0.1.0.2. GraalVM for JDK: 17.0.21.0.2, 21.0.13.0.2. GraalVM Enterprise: 21.3.20.0.2. These are the builds that include the CVE-2026-91403 intermediate block but still ship eMudhra root CAs. All earlier builds of these major versions are also vulnerable. |
| Fixed versions | Oracle advisory states updated builds are provided. Exact version strings for CVE-2026-114820 fix not yet confirmed (advisory published Oct 24). Manual workaround available immediately: remove emSign root CAs from cacerts via keytool -delete. CVE-2026-91403 fix (intermediate blocking via blocked.certs) ships in the .0.2 builds listed as 'affected' above. Third-party JDKs: Azul Zulu shipped CVE-2026-91403 fix on Oct 21; Temurin, Corretto, Microsoft OpenJDK pending as of Oct 23. |
| Exposure footprint | ~30,800 legitimate certificates were issued under the compromised intermediates per Google CT logs. Any Java application making outbound TLS connections to servers using these certificates — or any server that could be impersonated — is in scope. Java SE is estimated to run on 3+ billion devices (Oracle's historic claim). The attack surface is every unpatched JVM performing HTTPS, JDBC-over-TLS, LDAPS, Kafka TLS, or any TLS-protected connection. |
| Disclosure timeline | Apr 30, 2025: Weak keys generated during eMudhra key ceremony. Oct 17, 2026: Researcher 'Wayne' reports to vendors. Oct 18: eMudhra/Sectigo revoke intermediates. Oct 19-20: Chrome, Firefox, Apple, Microsoft deploy browser blocks. Oct 21: Oracle publishes CVE-2026-91403 (intermediate block). Oct 22: eMudhra announces exit from public SSL/TLS business. Oct 24: Oracle publishes CVE-2026-114820 (root CA removal). |
| Researchers | Wayne (initial discovery via Common CA Database audit, Oct 17). Scott Helme (key recovery demonstration, <1 second). Dennis Jackson (Mozilla, public disclosure coordination). Faulty key ceremony script attributed to eMudhra's internal HSM automation. |
Sources.
- Oracle Security Alert Advisory — CVE-2026-114820
- The eMudhra CA Compromise: Why Your JVM Is Vulnerable (Guillaume Laforge)
- eMudhra / emSign CA Certificate Security Incident Timeline (GitHub Gist)
- Distrusting Compromised eMudhra Intermediates in Java (BellSoft/Liberica)
- The eMudhra CA Compromise and Exit from Public SSL/TLS
- eMudhra Java Fix Update: JDK Vendor Builds and Workarounds (Safeguard.sh)
- eMudhra CA Key Compromise: Chrome and Firefox Blocked, Non-Browser Clients Need Updates (Rescana)
- eMudhra Quits Issuing Trust Certificates After Blunder (CyberNews)
Why this verdict
- Universal blast radius: Java SE is deployed on billions of devices across every enterprise. JSSE is the *default* TLS library — there is no opt-out. Every unpatched JVM trusts certificates signed by keys an attacker can recover in milliseconds. The combination of ubiquitous deployment and a broken cryptographic primitive affecting the TLS trust root is as severe as it gets short of RCE.
- Zero-friction key recovery: The compromised P-384 private keys are 8-bit scalars. Any attacker recovers all 8 by testing integers 1–255 against the public certificate — no exploit code, no special hardware, no zero-day. Scott Helme demonstrated full recovery on a laptop in under one second. This is not theoretical; it is mathematically certain.
- 17-month exposure window: The weak keys entered production in April 2025 and were publicly derivable until discovery on October 17, 2026. While no exploitation is confirmed, the trivial recovery threshold means any network-positioned adversary — state actor, compromised ISP, rogue WiFi operator — could have been silently forging TLS certificates for 17 months with zero forensic footprint.
- Java's unique blindness: Unlike browsers that deployed OneCRL/CRLSets blocks within hours, Java's JSSE has OCSP/CRL checking disabled by default and does not enforce Certificate Transparency. Even after eMudhra and Sectigo revoked the intermediates on Oct 18, unpatched JVMs blindly trust them. This makes Java the single largest unprotected ecosystem.
- Role multiplier: Java is canonical in virtually every high-value deployment role. (1) CI/CD + supply chain: Jenkins, Maven, Gradle, and Artifactory pull dependencies over TLS — a MITM injects malicious artifacts → supply-chain-scale compromise across every downstream build. (2) Identity tier: Keycloak, Spring Security, and SAML/OIDC libraries validate tokens over TLS — a MITM forges authentication responses → domain-scale identity compromise. (3) Data tier: JDBC, Kafka, and Elasticsearch clients connect over TLS — a MITM reads or modifies query results → regulated-data breach. (4) Microservices mesh: Spring Boot / Quarkus services use mTLS for inter-service calls — a MITM on the service mesh intercepts all east-west traffic → fleet-scale data exfiltration. In ALL these roles, the chain succeeds because JSSE is the trust layer, and >10% of Java SE installations *are* these high-value roles by definition. The verdict floor is CRITICAL.
Why not higher?
The CVSS score of 9.1 already reflects near-maximum severity. A 10.0 would require either scope change (S:C — the attacker pivots to a different security authority) or availability impact (A:H). Neither applies: the attacker compromises confidentiality and integrity of the vulnerable Java component's TLS sessions but does not crash the JVM or pivot to a separate trust domain automatically.
Why not lower?
Network interposition is the only friction point, but it is NOT sufficient to downgrade below CRITICAL. First, MITM is the *expected* threat model for TLS — the entire point of certificate validation is to prevent exactly this, and the broken CA keys nullify that protection. Second, for internet-facing Java clients (CI/CD pulling from Maven Central, API gateways calling external services, mobile backends), the attacker needs only a position on any network hop — achievable via DNS poisoning, BGP hijacking, cloud VPC lateral movement, or rogue WiFi. Third, the 17-month window and trivial key recovery mean the precondition may already have been satisfied silently. Fourth, the role multiplier across CI/CD, identity, and data tiers means the blast radius upon success is domain-scale or supply-chain-scale. Downgrading to HIGH would dramatically undercount the risk to any organization running Java backends.
Crowdsourced verification payload.
Run this script on each target host where a JDK or JRE is installed. Pass the Java home directory as the first argument, or let it auto-detect via JAVA_HOME or which java. Requires read access to cacerts (no root needed). Example: bash check_cve_2026_114820.sh /usr/lib/jvm/java-21-openjdk
#!/usr/bin/env bash
# CVE-2026-114820 — Detect trusted eMudhra root CAs in Java cacerts
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -euo pipefail
JH="${1:-${JAVA_HOME:-}}"
if [ -z "$JH" ]; then
if command -v java &>/dev/null; then
JB="$(readlink -f "$(command -v java)" 2>/dev/null || command -v java)"
JH="$(cd "$(dirname "$JB")/.." && pwd)"
else
echo "UNKNOWN — no Java found; set JAVA_HOME or pass path as argument"
exit 2
fi
fi
KT="$JH/bin/keytool"
if [ ! -x "$KT" ]; then
echo "UNKNOWN — keytool not found at $KT"
exit 2
fi
# Locate cacerts (JDK 9+ vs JDK 8 layout)
CS=""
for p in "$JH/lib/security/cacerts" "$JH/jre/lib/security/cacerts"; do
[ -f "$p" ] && CS="$p" && break
done
if [ -z "$CS" ]; then
echo "UNKNOWN — cacerts not found under $JH"
exit 2
fi
echo "[*] JAVA_HOME: $JH"
echo "[*] cacerts: $CS"
VER=$("$JH/bin/java" -version 2>&1 | head -1 || true)
echo "[*] Version: $VER"
# List all aliases in the trust store
ALIASES=$("$KT" -list -keystore "$CS" -storepass changeit 2>/dev/null || true)
# Check for eMudhra emSign root CAs
FOUND=0
for alias in emsigneccrootcag3 emsignrootcag1 emsignrootcag2; do
if echo "$ALIASES" | grep -qi "$alias"; then
echo " [!] Trusted emSign root present: $alias"
FOUND=$((FOUND + 1))
fi
done
# Informational: check if intermediate blocking is in place (CVE-2026-91403)
BC=""
for p in "$JH/lib/security/blocked.certs" "$JH/jre/lib/security/blocked.certs"; do
[ -f "$p" ] && BC="$p" && break
done
if [ -n "$BC" ]; then
BCCOUNT=$(grep -cE '^[0-9A-Fa-f]{40,}' "$BC" 2>/dev/null || echo 0)
echo " [i] blocked.certs hash entries: $BCCOUNT"
else
echo " [-] No blocked.certs file found"
fi
echo ""
if [ "$FOUND" -eq 0 ]; then
echo "PATCHED — eMudhra emSign root CAs not found in trust store."
exit 0
else
echo "VULNERABLE — $FOUND eMudhra emSign root CA(s) trusted in cacerts."
echo " Fix: keytool -delete -keystore $CS -storepass changeit -alias <alias>"
echo " Then restart all JVM processes."
exit 1
fi