Java and the eMudhra Certificate Compromise: CVE-2026-91403, CVE-2026-114820, and What to Update

Oracle and OpenJDK shipped two out-of-band fixes in four days after the private keys of eight eMudhra intermediate certificates turned out to be weak. Why the October Critical Patch Update builds are not enough, which Java builds to install, how Linux packages and Docker images differ, and what to do if you cannot update today.

Published 9 min read
Laptop showing source code on a desk beside a small potted plant

Java teams had a busy week. Oracle released its quarterly Critical Patch Update on 20 October 2026, and a day later both Oracle and the OpenJDK project issued an emergency alert for CVE-2026-91403, rated 9.1. On 24 October a second alert, CVE-2026-114820, followed because the first fix did not go far enough. Neither is a bug in Java code. Both come from eMudhra, a certificate authority whose compromised intermediate certificates were still trusted by the JDK. A server that installed the October update promptly can therefore still be exposed.

What Happened at eMudhra

eMudhra is a certificate authority based in Bengaluru that sells TLS certificates under the emSign brand. In April 2025 it created eight intermediate certificates, six for TLS and two for code signing. A flaw in the key generation ceremony left their private keys cryptographically weak, so weak that, according to published reports, one of the keys had the value 4. Whoever recovers such a key can issue a certificate for any domain, and every client that trusts the chain will accept it.

The problem surfaced on the weekend of 17 October 2026. Chrome blocked the intermediates within two hours of receiving the report, Mozilla did the same that evening, Apple followed on 19 October and Microsoft on 20 October. eMudhra revoked all eight certificates on 19 October and said its root keys were not affected. Chrome is removing the emSign ECC Root CA G3 root on 27 October, and Google has asked sites with certificates under that root to replace them.

Browsers update their trust lists on their own. Java does not. A standalone JDK carries its own trust store, a file called cacerts, and that file only changes when the JDK is updated or an administrator edits it.

Two CVEs in Four Days

CVEPublishedCVSS 3.1What the fix does
CVE-2026-9140321 October 20269.1Adds the eight compromised intermediates to the JDK blocklist (blocked.certs).
CVE-2026-11482024 October 20269.1Removes four roots from cacerts: emSign Root CA G1, G2, and ECC G3, plus Sectigo AAA Certificate Services, which had cross-signed the same keys. Tracked as JDK-8395690.

The second CVE exists because blocking the eight intermediates by fingerprint was not enough. The same weak keys had also been cross-signed under a Sectigo root, so other chains built on those keys would still be trusted. OpenJDK lists the .0.2 builds released for the first alert, such as 25.0.5.0.2 and 21.0.13.0.2, as affected by CVE-2026-114820. In practice, a fix for the first CVE alone does not close the hole.

Both CVEs are rated as exploitable over the network with no login and no user interaction, with high impact on confidentiality and integrity. There is one real precondition: the attacker has to sit between the Java application and the server it talks to, for example on a compromised router, public Wi-Fi, a hijacked DNS record, or a hostile network along the path. From there, they can present a forged certificate that Java accepts as valid.

Why Backend Teams Should Care

The usual picture of an HTTPS attack is a browser user on café Wi-Fi. For Java, the more serious case is a backend service acting as a client. A Spring Boot application that calls a payment gateway, a bank API, a courier tracking service, or a supplier system sends API keys, bearer tokens, and customer data over TLS. If that connection can be intercepted with a certificate Java trusts, the attacker can read those credentials and alter the responses. The same applies to JDBC connections over TLS, Kafka and message brokers, LDAP, outgoing SMTP, and webhook calls.

Two code signing intermediates are also in the set, so signed JAR verification is affected. Tools that check JAR signatures can be shown code signed with a forged certificate that appears legitimate.

The Regular October Update Still Matters

The certificate issue overshadowed the Critical Patch Update of 20 October, which brought 55 Java SE fixes, 49 of them exploitable remotely without authentication. None scored above 7.5. The highest were CVE-2026-43660 in JavaFX (WebKitGTK), which needs user interaction, and CVE-2026-91484 in the Java plugin, which requires local access. None was reported as exploited. The October baseline builds are 8u511, 11.0.33, 17.0.21, 21.0.13, 25.0.5, and 27.0.1. Java 26 reached the end of its support in September 2026 and does not receive this update.

The catch is that Oracle lists exactly those baseline builds as affected by CVE-2026-91403. Teams that patched on 20 October and stopped there are still exposed to the certificate issue.

Which Build to Install

The most reliable rule comes from OpenJDK: install a build whose release notes mention JDK-8395690 or CVE-2026-114820. Version numbers differ between vendors, and builds for different lines arrive on different days.

  • Oracle JDK: download the latest build for your line and check that its release notes mention CVE-2026-114820. A build ending in .0.2 only covers the first alert.
  • OpenJDK builds from jdk.java.net: 27.0.1.0.3 was available by 26 October.
  • Eclipse Temurin, Amazon Corretto, Microsoft Build of OpenJDK, Azul Zulu, and Red Hat build of OpenJDK: follow each vendor's release notes. As of 26 October several Temurin builds and the Homebrew openjdk packages for older lines were still listed as affected.
  • Java 8: version reporting is inconsistent between Oracle and OpenJDK for this line, so rely on the release notes rather than the build number alone.

Linux Packages, Docker, and Debian

How Java gets its certificates decides what you need to do. OpenJDK packages on Arch Linux, Fedora, Gentoo, Oracle Linux, and RHEL read the operating system trust store, so updating ca-certificates through the package manager is likely enough. Debian, Ubuntu, and Devuan are different. Because of a long-standing bug, updating ca-certificates and ca-certificates-java does not rebuild the Java keystore. As root, delete /etc/ssl/certs/java/cacerts and run update-ca-certificates --fresh.

FreeBSD and Homebrew packages do not use the system store, so the Java package itself has to be updated. The same goes for Docker images built on a standalone JDK, which carry the cacerts file inside the image. Rebuild them once the base image publishes a fixed tag, and redeploy. An image that was built last week will not change by itself.

Do not forget runtimes that ship inside other products. Application servers, IDEs, Jenkins agents, Elasticsearch, Kafka, and many vendor appliances bundle their own JDK with their own cacerts, and an operating system update does not touch them.

If You Cannot Update Today

OpenJDK publishes interim measures at openjdk.org/emudhra, including a small CheckCerts.java program that tells you whether a runtime still trusts the affected chains. The page no longer recommends replacing blocked.certs, because that only addresses the first CVE. There are two options instead.

  1. 1Back up the cacerts file of each Java installation. On JDK 11 and later it sits in $JDK_HOME/lib/security/cacerts, on JDK 8 in $JDK_HOME/jre/lib/security/cacerts.
  2. 2Remove the four roots with keytool -delete -cacerts -alias, once each for "emsignrootcag1 [jdk]", "emsignrootcag2 [jdk]", "emsigneccrootcag3 [jdk]", and "comodoaaaca [jdk]". On JDK 8, add -keystore with the path above. A "does not exist" message means the root was already absent.
  3. 3Restart every Java process that uses that installation. A running JVM keeps the trust store it loaded at startup.
  4. 4Repeat for every JDK on the machine, including the ones bundled inside other software.

The second option is revocation checking. Starting Java with -Dcom.sun.net.ssl.checkRevocation=true and -Dcom.sun.security.enableCRLDP=true makes TLS connections reject the revoked eMudhra intermediates. It depends on fetching revocation lists over the network, which can fail or add latency, so treat it as a stopgap. For signed JARs on JDK 17 and later, jarsigner -verify -revcheck -strict performs the same check.

One caution applies to both the update and the manual removal. AAA Certificate Services is an old root that some legitimate chains still end in. If a partner API is served with such a chain, connections from Java may fail after the change. Test outbound connections to payment, banking, and other critical services in staging before rolling out to production.

Not Only Java

Every runtime that ships its own trust store had to respond. Go released 1.27.3 and 1.26.10 for the same issue under CVE-2026-111943, and Python certifi, pip, Electron, and rustls-webpki were updated as well. The Node.js security releases of 21 October also refreshed the bundled root certificates for this reason. If your systems mix languages, check each runtime separately rather than assuming one operating system update covers all of them.

Checklist

  1. 1List every Java runtime in use: application servers, containers, CI agents, and products that bundle their own JDK.
  2. 2For each one, note where its certificates come from: the bundled cacerts file or the operating system store.
  3. 3Install a build whose release notes mention CVE-2026-114820, or update ca-certificates on distributions that use the system store. On Debian and Ubuntu, rebuild the Java keystore as described above.
  4. 4Rebuild and redeploy container images, then restart all Java processes.
  5. 5Run CheckCerts.java from openjdk.org/emudhra against each runtime to confirm the affected chains are no longer trusted.
  6. 6Test outbound TLS connections to critical third-party services.
  7. 7Plan the January 2027 Critical Patch Update, due on 19 January, into the next maintenance window.

Incidents like this show why an inventory of runtimes matters. Teams that know where every JDK lives can finish this work in an afternoon. Teams that do not will spend days finding them. If you need help auditing or updating Java services across servers and containers, our managed service team can take it on.

Key takeaways

  • CVE-2026-91403 and CVE-2026-114820 come from eight eMudhra intermediate certificates with weak private keys. Both are rated 9.1.
  • The October Critical Patch Update builds (8u511, 11.0.33, 17.0.21, 21.0.13, 25.0.5, 27.0.1) are affected, and so are the .0.2 builds released for the first alert.
  • Install a build whose release notes mention JDK-8395690 or CVE-2026-114820. On Debian and Ubuntu, also rebuild /etc/ssl/certs/java/cacerts.
  • Docker images and products that bundle a JDK need their own update. An operating system patch does not reach them.
  • If you cannot update yet, remove the four roots with keytool or enable revocation checking, and test critical outbound connections afterwards.
Share this article

Related articles

More articles on software development, AI, cloud, and infrastructure.

Let’s talk

Looking for a software development partner?

Tell us about your project, what you need to build, and the challenges you are facing. We can discuss the technical approach, scope, timeline, and estimated cost.

Start a conversation