JavaFormatter Free Online Java Formatter
Security

CVE-2026-91403: Critical Java Vulnerability and How to Fix It

2026-10-29 · 6 min read

On October 21, 2026, one day after its regular October Critical Patch Update, Oracle published an out-of-band Security Alert for CVE-2026-91403, a critical vulnerability in the Java Secure Socket Extension (JSSE) that ships with Oracle Java SE and GraalVM. The CVSS 3.1 base score is 9.1, and the flaw is remotely exploitable without authentication and without user interaction. The root cause is unusual: this is not a bug in Java code, it is a trust problem. The private keys of eight intermediate CA certificates operated by eMudhra were compromised, and the affected JDKs still trusted them. This guide explains what that means in practice, which versions are affected, how to check your installs, and how to fix it, including a manual workaround if you cannot update right away.

What the Vulnerability Actually Is

Every JDK ships a keystore named cacerts holding the certificate authorities that Java trusts. When your application opens a TLS connection, JSSE validates the certificate the other side presents against that list. CVE-2026-91403 exists because the private keys of eight eMudhra intermediate CA certificates were compromised: whoever holds those keys can issue server certificates that chain up to roots Java still trusts, and JSSE will accept them as genuine.

In practice this is a man-in-the-middle exposure. An attacker positioned on the network path between your JVM and the server it talks to can present a forged certificate, terminate the TLS connection, and read or alter the traffic. The CVSS vector makes the scope explicit: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N, which reads as attack over the network, low complexity, no privileges, no user interaction, and high impact on both confidentiality and integrity. Availability is not affected.

What Is at Risk

Any Java process that validates certificates with an affected JDK is in scope. The most common case is outbound TLS: server-side applications calling payment providers, webhooks, or partner APIs over HTTPS, batch jobs pulling external feeds, and message brokers connecting over TLS. Anywhere else JSSE validates a certificate presented to it, such as mutual-TLS client certificate checks, is exposed the same way. Desktop and sandboxed Java clients that connect over untrusted networks are the classic target.

Affected Versions

Oracle lists the following supported versions as affected, and everything earlier in each release line is affected as well:

  • Oracle Java SE: 8u511, 8u511-perf, 11.0.33, 17.0.21, 21.0.13, 25.0.5, and 27.0.1
  • Oracle GraalVM for JDK: 17.0.21 and 21.0.13
  • Oracle GraalVM Enterprise Edition: 21.3.20
  • OpenJDK distributions: the OpenJDK advisory lists 27.0.1, 25.0.5, 21.0.13, 17.0.21, 11.0.32.1, and 8u504 and earlier

The Oracle and OpenJDK lists differ on paper because the vendors number their JDK 8 and JDK 11 builds differently, a recurring source of confusion during this kind of alert. Do not try to map version numbers between vendors. Instead, check your own distributor's release notes, whether you run Temurin, Corretto, Zulu, Liberica, or another build, for a release that references the fix, which is tracked in OpenJDK as JDK-8395690. Some vendor notes reference CVE-2026-114820 alongside or instead of CVE-2026-91403 for the same certificate-distrust change.

How to Check What You Are Running

Run this everywhere Java runs: developer machines, CI runners, application servers, containers, and desktop apps that bundle their own runtime:

java -version

The version line tells you the release line you are on, such as 17.0.x, 21.0.x, or 25.0.x. For a definitive verdict on the trust store itself, the OpenJDK team published a small diagnostic program, CheckCerts.java, that reports whether the keystore still contains the affected eMudhra certificates. It runs on JDK 8 and later and is linked from the OpenJDK eMudhra incident page.

The Fix: Update to a Build That Distrusts the Certificates

Fixing CVE-2026-91403 does not require any change to your application code. The patched JDK builds simply stop trusting the eight compromised eMudhra intermediate certificates. Update each affected install to the current build from your distributor, then restart the running JVMs. An updated JDK on disk does nothing for a process that is still running on the old one. Web services, schedulers, and app servers should be restarted in your normal maintenance window; no reconfiguration is needed beyond the update itself.

If You Cannot Update Yet: Remove the Roots Manually

When a same-day update is not realistic, say for locked-down production windows, certified runtimes, or appliances, you can remove the affected trust anchors from the keystore yourself. Back up the keystore first, then delete the four eMudhra-related root aliases. On JDK 11 and later, where the keystore lives at $JAVA_HOME/lib/security/cacerts:

keytool -delete -cacerts -alias "emsignrootcag1 [jdk]"
keytool -delete -cacerts -alias "emsignrootcag2 [jdk]"
keytool -delete -cacerts -alias "emsigneccrootcag3 [jdk]"
keytool -delete -cacerts -alias "comodoaaaca [jdk]"

On JDK 8, the keystore lives at $JAVA_HOME/jre/lib/security/cacerts; pass it explicitly and repeat for all four aliases:

keytool -delete -keystore $JAVA_HOME/jre/lib/security/cacerts -alias "emsignrootcag1 [jdk]"

Restart live runtime instances afterward, or they keep serving decisions made from the old keystore state. One trade-off to know: deleting the roots is broader than the official fix, which distrusts exactly the eight compromised intermediates. If something you connect to legitimately presents an eMudhra-issued certificate, TLS validation will fail after this workaround, so treat that connection as an exception to handle during the update.

OS-Packaged and Containerized JDKs

Distributions that wire the JDK to the system trust store are fixed by updating the OS certificates instead. On Oracle Linux, RHEL, Fedora, Arch, and Gentoo, updating the ca-certificates package is likely sufficient. Debian and Ubuntu have a separate problem: a known bug in ca-certificates-java can leave the generated keystore stale, so delete and rebuild it:

rm -f /etc/ssl/certs/java/cacerts
update-ca-certificates --fresh

For container images, rebuild on refreshed base images and verify inside the image with java -version against the distributor's release notes for that tag. A rebuilt image that still resolves to the old JDK build has fixed nothing.

Turn On Revocation Checking While You Are At It

Certificate revocation checking would have limited the damage from compromised CA keys, and Java has the support built in but switched off by default. For TLS applications, start the JVM with:

-Dcom.sun.net.ssl.checkRevocation=true -Dcom.sun.security.enableCRLDP=true

For signed JARs on JDK 17 and later, jarsigner -verify -revcheck -strict checks revocation at verification time. Test before rolling these out broadly: endpoints whose CRL or OCSP responders are unreachable will start failing validation once checking is on, which trades one class of outage for another.

A Patching Checklist

  1. Inventory every JDK in the estate with java -version, including CI runners, container base images, and bundled runtimes.
  2. Update each install to a build whose release notes reference CVE-2026-91403 or JDK-8395690.
  3. Restart long-running JVMs so they pick up the updated keystore.
  4. Re-verify TLS connectivity to your critical endpoints.
  5. On Debian and Ubuntu hosts, apply the ca-certificates-java rebuild even if the JDK package itself was updated.

The change itself is small, but the blast radius of a trusted-CA compromise is not. Treat this alert as a same-week patch, not a someday item. And if patching does touch your Java code or configuration, keep the diff reviewable: separate formatting-only changes into their own commit and run the touched files through the online Java formatter before you open the pull request.

Related guides

Frequently Asked Questions About CVE-2026-91403

What is CVE-2026-91403?

CVE-2026-91403 is a critical vulnerability in the Java Secure Socket Extension (JSSE) of Oracle Java SE and GraalVM, disclosed by Oracle on October 21, 2026. The private keys of eight eMudhra intermediate CA certificates were compromised, allowing man-in-the-middle attackers to read and modify TLS traffic from Java applications. Oracle rates it 9.1 on the CVSS 3.1 scale.

Which Java versions are affected by CVE-2026-91403?

Oracle lists Java SE 8u511, 8u511-perf, 11.0.33, 17.0.21, 21.0.13, 25.0.5, and 27.0.1 as affected, plus Oracle GraalVM for JDK 17.0.21 and 21.0.13 and GraalVM Enterprise Edition 21.3.20. The OpenJDK advisory lists 27.0.1, 25.0.5, 21.0.13, 17.0.21, 11.0.32.1, and 8u504 and earlier. Version numbering differs by distributor, so check your vendor's release notes.

How do I fix CVE-2026-91403?

Update to your distributor's latest JDK build whose release notes reference CVE-2026-91403 or JDK-8395690, then restart running JVMs. If you cannot update immediately, delete the four eMudhra root aliases from the cacerts keystore with keytool, back up the keystore first, and restart.

Is OpenJDK affected, or only Oracle JDK?

OpenJDK builds are affected too, because the compromised eMudhra certificates sat in the shared cacerts trust store, not only in Oracle's distribution. Temurin, Corretto, Zulu, and other distributors published corresponding updates; the OpenJDK fix is tracked as JDK-8395690.

Do I need to restart my Java services after patching?

Yes. A JVM that started before the update keeps running with the old keystore state. Restart long-running services after updating, and immediately after any manual keystore edit.

More Free Developer Tools

DevToolCore

JSON formatter, regex tester, Base64, URL encoder, and 15+ more dev tools.

FontGenerator

14 Unicode font styles for social media, Discord, and anywhere you paste text.

CyberFengShui

Online Feng Shui compass with flying star analysis and AI interpretation.