TL;DR: CVE-2026-91403 (CVSS 9.1) is not a remote code execution bug. Java still trusts eight eMudhra intermediate certificate authorities, and anyone can compute their private keys. An attacker who can sit between your Java application and a server it calls over TLS can impersonate that server. To fix it, update to a patched JDK build. If your vendor hasn’t shipped one yet, add the compromised certificates to blocked.certs and add a second control alongside it. Both are covered below, including a Dockerfile you can adapt.
Updates
October 22, 2026, 15:08 UTC
A Temurin 25.0.5 build is appearing, but don’t assume it fixes this CVE. Search results for Adoptium’s Temurin 25 release list now show jdk-25.0.5+8, dated October 22, as the latest release. Our direct view of the same page still showed 25.0.4.1, so the release may still be rolling out, and the container image tags may lag behind it.
Version 25.0.5 is the October 20 scheduled update, which Oracle and OpenJDK list as still affected. The upstream fix is in the later 25.0.5.0.2 builds. Temurin’s October release was expected to include the updated Mozilla root list that drops the emSign root, which would close the emSign chain but not necessarily add the blocked intermediates. Before you remove the workaround from images that move to the new build, test both chains against it, and keep the blocked.certs entries unless the release notes confirm the full fix. The same applies to the other Temurin versions in the October release as they appear.
October 22, 2026, 14:28 UTC
Temurin’s October release will include an eMudhra change, but isn’t out yet. On Adoptium’s October 2026 release tracker (8u512, 11.0.33, 17.0.21, 21.0.13, 25.0.5 and 27.0.1), a maintainer noted on October 21 that the release will pick up a change updating Temurin’s root list to NSS 3.131.1, the Mozilla release that removed emSign ECC Root CA – G3. Temurin’s root list is built from Mozilla’s, which already left out AAA Certificate Services. When we checked, the tracker showed no builds started, and a commenter’s question about whether the Sectigo cross-signed path is also handled had no public answer.
What this means: keep the workaround in place until the new Temurin build is out, and before you remove it, run the test hosts for both chains against the new build. If the release only removes the emSign root, keep the blocked.certs entries anyway, since they also protect custom trust stores that might still contain either root. We’ve added this check to the checklist.
October 22, 2026, 12:53 UTC
RHEL and UBI don’t have a fixed ca-certificates package yet. The post previously said updating ca-certificates is enough for Java from Linux distribution packages. That holds for Debian and Ubuntu, but as of October 22 Red Hat had not shipped a fixed package for RHEL or UBI images. Until it does, follow the workaround in Red Hat’s bulletin RHSB-2026-012, which distrusts the affected roots in the system trust store. We’ve corrected the distribution table.
No change for Temurin, Corretto, Oracle or OpenJDK releases since the previous update.
October 22, 2026, 12:01 UTC
The fingerprint list now covers re-encoded certificates. A package maintainer’s fix for their Temurin-based JDK packages blocks 48 fingerprints instead of 16: each certificate as issued, with the signature algorithm’s NULL parameter toggled, and for the ECDSA-signed ones with the signature value flipped from s to n − s. These are the same variants OpenJDK’s own tooling generates for blocked.certs, and they match the re-encodings in Sonatype’s bypass. Their build tests showed Java accepts the NULL-toggled copies, so a 16-line list leaves a working re-encoding of every certificate. We recomputed all 48 fingerprints from the public certificates and got exactly the same list, and we’ve replaced the list and the Dockerfile check in this post.
If you already deployed the 16-line list, add the 32 new lines and rebuild. Removing both roots still matters as a second layer.
No change for Temurin, Corretto, Oracle or OpenJDK releases since the previous update.
October 22, 2026, 10:45 UTC
Removing the roots from cacerts may not be enough on its own. A detailed guide from Safeguard points out that a JVM doesn’t always read cacerts. If the javax.net.ssl.trustStore property is set, the JVM uses that file instead, and if a jssecacerts file exists next to cacerts, it wins silently. Runtimes built with jlink carry their own frozen copy, and client libraries and application servers often take their own trust store path. Each of those needs the same root removal. We’ve added a section on this to the workaround and updated the checklist.
Test both chains. Because builds differ in which roots they ship, a JDK can reject the chain through the emSign root and still accept the one through AAA Certificate Services, or the other way round. Only a failure on both kinds of test host proves the fix. We’ve updated the verification step.
No change for Temurin, Corretto, Oracle or OpenJDK since the previous update.
October 22, 2026, 10:13 UTC
BellSoft (Liberica JDK) recommends removing both roots. In its guidance, BellSoft’s temporary mitigation is the same as the recommended second layer in this post: delete emSign ECC Root CA – G3 and AAA Certificate Services from cacerts. Liberica is more exposed than some other builds because its cacerts still contains the AAA root, and in BellSoft’s tests it accepted all twelve compromised test chains. Builds based on Mozilla’s root list, such as Temurin, don’t ship the AAA root and accepted only the six chains through the emSign root.
Root aliases differ between vendors. BellSoft notes that Liberica names the roots emsigneccrootcag3 [jdk] and comodoaaaca [jdk], while Temurin uses aliases that start with cn_emsign_ecc_root_ca__g3. Check each certificate’s subject with keytool -list -v before deleting anything. We’ve added this to the Dockerfile comments.
No change for Temurin, Corretto, Oracle or OpenJDK since the previous update.
October 22, 2026, 10:03 UTC
Azul Zulu has shipped a fix. Azul published an out-of-cycle release on October 21 for Zulu 6, 7, 8, 11, 17, 21, 25 and 27. It includes the upstream OpenJDK change JDK-8395142, which blocks the compromised intermediates in blocked.certs (blacklisted.certs on Java 8 and older), so no manual workaround is needed after upgrading. For installations that can’t be upgraded yet, Azul publishes a replacement block-list file and script.
Exploiting unpatched clients has become easier. According to SafeDep, mitmproxy 12.3.0, released on October 22, can sign intercepted traffic with a recovered eMudhra key, so an attacker who can intercept an affected client’s traffic doesn’t need custom tooling. CT log researchers also report that certificates for google.com signed with these keys are already public. An attacker still needs a position on the network path, but once there, the rest is off-the-shelf. We’ve updated the risk assessment below accordingly.
No change yet for Temurin and Corretto: neither had published a fixed release when we checked, and the Corretto pull requests were still open.
October 22, 2026, 09:45 UTC
Amazon Corretto has a proposed fix that goes further than blocking the eight intermediates. A set of community pull requests, one for each supported Corretto version (11, 17, 21 and 25), removes both roots involved from Corretto’s trust store: eMudhra’s emSign ECC Root CA – G3 and Sectigo’s AAA Certificate Services. The Corretto 17 pull request was opened first, on October 20, and the others followed on October 21. A Corretto maintainer replied on both the 17 and 21 pull requests that an urgent release is being prepared. All four were still open when we updated this post.
That matches what the rest of the ecosystem is doing. Mozilla removed the emSign ECC root in NSS 3.131.1 on October 20, and Chrome’s removal reaches all devices on October 27. Debian dropped both roots from its ca-certificates package. Chrome and Firefox already stopped trusting AAA Certificate Services for TLS before this incident.
Removing the two roots also closes the fingerprint-bypass gap described further down, which a hand-edited blocked.certs can’t. We’ve updated the Dockerfile, the recommendations and the checklist: removing both roots is now the recommended second layer next to blocked.certs.
What happened
In April 2025, the Indian certificate authority eMudhra created eight intermediate CAs with elliptic-curve keys. Because of a bug in its key-generation script, the private keys of those intermediates were tiny integers, small enough that anyone can recover them by brute force from the public key printed in each certificate (Mozilla bug 2083449). Anyone who has an intermediate CA’s private key can issue a valid-looking certificate for any domain.
Browsers reacted within hours. Chrome pushed a CRLSet block the evening the report arrived (Saturday, October 17, 2026), Mozilla blocked the intermediates through OneCRL the same night, and Apple and Microsoft followed on October 19 and 20.
Java is a separate case. Its default TLS stack (JSSE) doesn’t receive any of those browser revocation feeds, has revocation checking switched off by default, and doesn’t require Certificate Transparency. A standalone JDK therefore keeps accepting these chains. Six of the eight intermediates issue TLS certificates and two issue code-signing certificates. They chain up to two roots: eMudhra’s own emSign ECC Root CA – G3 and Sectigo’s AAA Certificate Services. Sectigo had cross-signed the same keys, so the path through the Sectigo root is compromised too.
On October 21, Oracle and OpenJDK published out-of-band advisories. Oracle lists Java SE 8u511, 8u511-perf, 11.0.33, 17.0.21, 21.0.13, 25.0.5 and 27.0.1, GraalVM for JDK 17.0.21 and 21.0.13, and GraalVM Enterprise Edition 21.3.20 as affected, along with all earlier versions. This list includes the scheduled updates released the day before, on October 20.
What could be exploited, and what can’t
The 9.1 score comes from the CVSS vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N, with JSSE as the affected component. It means network-reachable, no authentication, and high confidentiality and integrity impact. Availability impact is none, and the vector says nothing about code execution. You may see the issue called “RCE” on social media, but neither Oracle nor OpenJDK describes it that way.
A realistic attack requires the attacker to get between your Java process and a server it talks to, for example through a compromised network segment, DNS or BGP hijacking, or a malicious proxy. From there they present a forged certificate for the real hostname, and your application accepts it. They can then read and modify traffic in both directions: API credentials, tokens, payloads and responses. The two code-signing intermediates also matter if you verify signed JARs.
For comparison, Log4Shell scored 10.0 and could be exploited with one crafted string. This vulnerability needs a privileged network position first. Once an attacker has that position, though, the rest is easy: the private keys are public, common interception tooling already supports them, and forged certificates for well-known domains are circulating. Put it through your fast-track patch process and apply the workaround today rather than waiting for the next release window. Treat it as an emergency if your Java services make outbound TLS calls across networks you don’t control, such as the public internet, shared hosting networks or third-party proxies.
How to fix it in Oracle Java
Install the patched build listed in the Java SE patch availability document that Oracle’s security alert links to. According to secondary sources, the fixed builds are 27.0.1.0.2, 25.0.5.0.2, 21.0.13.0.2, 17.0.21.0.2 and 11.0.33.0.2. Confirm the numbers in Oracle’s document before you rely on them.
If you can’t upgrade immediately, Oracle offers a replacement blocked.certs file, with one version for Windows and one for other platforms. Back up the current $JAVA_HOME/lib/security/blocked.certs, copy over any entries you added to it yourself, then swap in Oracle’s file. On Java 8 the file is called blacklisted.certs and lives in the same directory.
How to fix it in other Java distributions
How you fix it depends on where your JDK gets its trusted roots:
| How Java was installed | Where trust comes from | What to do |
|---|---|---|
| Standalone builds: Temurin, Liberica, Zulu, Corretto, tarballs, installers, official Docker images | The JDK’s own cacerts and blocked.certs | Update to your vendor’s fixed build (Azul Zulu has one). Until yours ships, use the workaround below. |
| Linux distro packages (Debian, Ubuntu, Fedora, RHEL and similar) | Usually the OS certificate store | Update the ca-certificates package. On RHEL and UBI, where no fixed package was available on October 22, apply the workaround in Red Hat’s bulletin until one ships. |
| Homebrew and FreeBSD | Bundled with the Java package | Update the Java package itself. |
Two traps to watch for with standalone builds and containers:
- Running
apt upgrade ca-certificatesinside a vendor JDK image does nothing for Java. Vendor JDKs ship their owncacerts, and Temurin’sUSE_SYSTEM_CA_CERTS=1option only adds the OS roots on top. It never removes anything. - Not every vendor has shipped a fix yet. Azul Zulu released one on October 21, but as of October 22, Temurin had no patched release, and Corretto’s fix was still in review for versions 11, 17, 21 and 25. Watch your vendor’s release announcements and container image tags. If you use an image that is built on top of a vendor JDK image, also check when that image was last rebuilt before you assume it contains the fix.
The workaround: patching blocked.certs in your image
blocked.certs lists certificates Java will refuse to trust even if they chain to a trusted root. It’s a plain text file: the first line declares Algorithm=SHA-256, and each following line is one certificate fingerprint. The workaround appends fingerprints for all 16 certificates (the 8 intermediates plus their 8 cross-signed copies), in every encoding Java is known to accept, which comes to 48 lines. In independent testing, a JDK patched this way refused the compromised chains even with revocation checking off, while ordinary HTTPS sites kept working.
The 16 “as issued” fingerprints come from the reporter’s impacted-intermediates.json. The other 32 cover re-encoded copies that an attacker can produce without the private key (see below). They follow the same rules OpenJDK’s own tooling uses to generate blocked.certs, as published in a package maintainer’s fix, and we recomputed all 48 independently from the public certificates before publishing. Save the list as emudhra-blocked.certs next to your Dockerfile. Comment lines are fine, because the build step only picks up the fingerprint lines. Check it against the sources rather than trusting a copy from a blog post, this one included.
# emudhra-blocked.certs: SHA-256 fingerprints of every known encoding of the
# 16 compromised eMudhra intermediate certificates (8 keys x 2 issuers).
# Per certificate: the DER as issued, the same with the signatureAlgorithm NULL
# parameter toggled, and for the ECDSA-signed (emSign-issued) ones the s -> n-s
# variant of each. 8 x 4 + 8 x 2 = 48 lines.
# Sources: impacted-intermediates.json (originals) and the variant set from
# github.com/gominimal/pkgs/pull/949, recomputed independently from the PEMs.
# EM DV TLS CA - G3B (issued by emSign Root TLS CA - G3)
42C4ACCD12C4F59597925E1A08A7A90102608543809308D50EC427E118BA1493
37E866582D43C35D7C17D47794B974F291B3047B868DC123382477F7A08AEFA8
CD740652E552D93EE64D7C9D1CC25228E466895889CEE25A11C962AB09906978
C5F1531C6331659C75A6411A088A65DAD7518FD91F57B64537A651B6DCD76AE0
# EM DV TLS CA - G3B (issued by AAA Certificate Services)
45A883F349AEDFD5F3A649B5498FFB121712BA8B448F3F2A91DBC5A766FCDDBE
C93F7B1EEF27CFD0F227DFE3F057D63833533890B7230B1821A424BD40848E33
# EM OV TLS CA - G3B (issued by emSign Root TLS CA - G3)
98B896625C0C230ADEEC3EB2CF6AAD5001ECF9156A68644E82374CE5833BC25B
33C1BCDC6DA52DF950B3B14121127DA1955F7F31F828497A7608986EB2DDCC09
8F580C6E34CEE7EE57B93BA9C0AC5FAEDD7BF3085F5EE9C6C0175A2555B111D0
50E71B08B9AC407B93D50EE90100CB6B6B41C956DC7AA86C5BAA38AE713CFD6A
# EM OV TLS CA - G3B (issued by AAA Certificate Services)
5F1DED4DD590AF74631290CF073B122A2AAC6A1FA479778A0BD43579BD832699
21182E577E5106B669322ABE6086FFF6B101E8C83FD2D01DC32D854961AAC832
# EM EV TLS CA - G3B (issued by emSign Root TLS CA - G3)
E7568FE6E12331F4FD7DE61DA4C7559D0F8EB192A218D4741A3BA75184333838
EF34030C01B13BF42B534072DCC3C75B13C009DC9241119ADA39E2C15E2AFD2E
C65CBC98295549BA940494A6214B9706E7115E64F3FE269412C5B48AEACB2222
B75104427B6A5BE55033AF50DC0FE3102181BE130E761D487A4E8178C93317DD
# EM EV TLS CA - G3B (issued by AAA Certificate Services)
579480AEA166290BD3C643589E795FC0D0E54E86505D180F1DFF99EFD3199512
75D8853BE99C87678E6C7BF9F684B31454D81DEB1C7F37B9FBC026A268337536
# EM DV TLS CA - G3C (issued by emSign Root TLS CA - G3)
0164D7CEAE5BB909C272AF151FF44B1177AE9B47D9424B94F1D9558C30934D19
A4B72DBD37256324B557B9176F8CBA4310DDFFBCC4609977E2463F3504A716C8
59CC5FD35A737B84682EDA26AD23F5ADE8AA847D5BEB3B38AB6CD62347925A66
A0ED2032C5249EE1A653F1F88005D9E779E385DF533B5C521137CEE5176CD7FC
# EM DV TLS CA - G3C (issued by AAA Certificate Services)
62B7F9868263F72F6911FC78CEAF72C1979158B7368BF648683BB2AA39B02E72
D8A50FA0068E9558E6C3BEE18CDB03B7EECBC3C56C1B2336B98AEE11644994B8
# EM OV TLS CA - G3C (issued by emSign Root TLS CA - G3)
CB6E15165AC802E9B3F993F16C25D41F4E81C21EBDE71AE1B012AC00BF9C7C3F
A104B1314DF8E02F7DE27DDC287D0961D6E6824AD4DAFC3D11064F24C1B653D5
558EC6CA13DA9B800FEDC9ACC3C18CA98BB19768F1309B60B5BB89793B3481CB
10E7E5BFDB55CFB78D0C21366654046182087A1960C079682513795665AA0C6B
# EM OV TLS CA - G3C (issued by AAA Certificate Services)
7485B51C0ED192878FA1D2F948FB529AE1842CC5086C4B67F7BE5B2039DE9489
A4328E058C867AF9CA8D468C388B72C250CE84BDB6BAF7F8C47C9A0B1CB35EEC
# EM EV TLS CA - G3C (issued by emSign Root TLS CA - G3)
432EC25F0D28DE9006D97BF752F17BBB2CD41F669933FCB072D9A1148D0261F3
169A0523C5E071AA4E298286DBD4EE0E40C8C06ABB6B0C077D132F001FA19240
7BA62FEC54E9D040556FCA70A6A88F03761C178FA1F7CB8390A73076849F55A2
8FED925362F62FFF90DD835BE6ADC32B02DEC8DF5E82D83E512F1C977D066E82
# EM EV TLS CA - G3C (issued by AAA Certificate Services)
FD9D5C2DBBD4995AB69B8D50C439D9527B00529199C2FD01B2174EB58F07021F
B7121039CAF13E03E52507F42DB56FA802FF119DA7591ABA8A2E842133DB7C9C
# EM OV CS CA - G3B (issued by emSign Root CS CA - G3)
9E39DE2881273ACC225A149C72BA3E0F51424963669AB633EE1DC7DF5DB067B4
5D8FC3ECDDB4DDB243AEE5C306BCFDE670ADF2D66B193DD3AA2D6B2FB91869BE
3B88E4B77FC53C45CA216700E39FC0EA7621A0A40FCB268215082E35D2BD5829
3C5456D4219BA2372273867FAC9A07104600391E96C7FDCDE3B4420C0F1F69BF
# EM OV CS CA - G3B (issued by AAA Certificate Services)
A496E23AC0CAB8155FC9B117B97EAE368EFCBB9041AEC8804D5A308D2D01C2D8
9E7617035CFF537C837E078A7CDC7FD9EB77BCE7DDF3DC6DBD5C50AAFC1F1FA7
# EM OV CS CA - G3C (issued by emSign Root CS CA - G3)
4B2460A466F95FD40113BCDCCA2CEB29B3B093921DE45474DA7DF48874C630B1
AB7292F82267333031F512379FDBADA949DFA49D3C046CC8FA7F34117C342986
A61FE79B019062DD3C6420BC20EAF64702CC1063C546A084DD0A0BCB915A14A9
4DED6F955374E40B8558A611A9719B2AB69AA6852AC50966EDC4B07DE4D4277C
# EM OV CS CA - G3C (issued by AAA Certificate Services)
84112972B8E59D14560AE7E7119654474AAD119990CF3722BFC1E3B91615E1FD
912A48745BFF2F14D1798B27858613DE1C0EB03C2BDE630AFD0DDD5251E1EBE1
Then add the patch to your runtime image. The example takes the base image as a build argument, so it works with whichever JDK image and version you run:
# Build with your own base image, pinned by digest, e.g.:
# docker build --build-arg BASE_IMAGE=eclipse-temurin:<version>-jre@sha256:<digest> .
ARG BASE_IMAGE
FROM ${BASE_IMAGE}
# --- Stopgap for CVE-2026-91403 ---------------------------------------------
# Remove this block once your vendor ships a build with the official fix.
COPY emudhra-blocked.certs /tmp/emudhra-blocked.certs
RUN set -eux; \
blocked="$JAVA_HOME/lib/security/blocked.certs"; \
test -f "$blocked"; \
cp "$blocked" "$blocked.orig"; \
fps="$(grep -E '^[0-9A-Fa-f]{64}$' /tmp/emudhra-blocked.certs | tr 'a-f' 'A-F')"; \
# Fail the build if the list is incomplete or malformed
test "$(printf '%s\n' "$fps" | wc -l)" -eq 48; \
printf '\n# CVE-2026-91403: compromised eMudhra intermediates\n%s\n' "$fps" >> "$blocked"; \
rm /tmp/emudhra-blocked.certs
# --- Recommended second layer: stop trusting both affected roots ------------
# Same approach as Corretto's proposed fix. Browsers already distrust both
# roots: emSign ECC Root CA - G3 (Mozilla, Chrome) and, for TLS,
# AAA Certificate Services (Chrome, Firefox).
# List the matching aliases in your image first. Some vendors don't ship
# AAA Certificate Services at all, so there may be only one:
# keytool -list -cacerts -storepass changeit | grep -i -E 'emsign|aaa|comodo'
# Alias names differ by vendor, e.g. "emsigneccrootcag3 [jdk]" and
# "comodoaaaca [jdk]" in Liberica, "cn_emsign_ecc_root_ca__g3,..." in Temurin.
# Confirm each subject with: keytool -list -v -cacerts -storepass changeit
# then delete each matching alias:
# RUN keytool -delete -cacerts -storepass changeit -noprompt -alias "<alias>"
# Before deploying, check that none of your outbound endpoints still chain
# to either root, or those connections will start failing.
# --- Optional extra layer: revocation checking ------------------------------
# Rejects the revoked intermediates, but every TLS handshake now needs to
# reach the CA's CRL endpoint, which breaks in egress-restricted networks.
# ENV JAVA_TOOL_OPTIONS="-Dcom.sun.net.ssl.checkRevocation=true -Dcom.sun.security.enableCRLDP=true"
# ----------------------------------------------------------------------------
# ... the rest of your image (app, user, entrypoint) ...
The same RUN step works on any image whose JDK sets JAVA_HOME, including application-server images built on a vendor JDK. Restart running JVMs after deploying, since blocked.certs is read at startup.
Check which trust store your JVM actually uses. blocked.certs lives in the JDK itself and is checked during certificate path validation whatever trust store the application uses, but root removal only helps in the trust store the JVM reads, and that isn’t always cacerts. Look for these before you assume you’re covered:
- A
javax.net.ssl.trustStoresystem property, in JVM options,JAVA_TOOL_OPTIONSor startup scripts. If it’s set, the JVM ignorescacerts. - A
jssecacertsfile next tocacertsin$JAVA_HOME/lib/security. It takes precedence overcacerts. - Trust stores configured inside client libraries, application servers, database and messaging drivers. Each one is a separate file to fix.
- Runtimes built with
jlink, which contain their own copy ofcacertsandblocked.certs. Patch the runtime you ship, not just the JDK you built it from.
To verify the patch, use the public test hosts listed on the reporter’s incident page, which serve certificates from the compromised intermediates. Some hosts serve the chain through the emSign root and others the chain through AAA Certificate Services, and a JDK can reject one while accepting the other, so test at least one of each. An HTTPS request from inside your patched container, using the same JVM and trust settings as your service, should fail with an untrusted-certificate error on every test host. The same request to any normal site should still succeed.
Why blocked.certs alone isn’t enough
Fingerprint blocklists have a known weakness here. A fingerprint is a hash of a certificate’s exact bytes, and Sonatype’s researchers showed that an attacker can change those bytes without the private key while the signature stays valid. For ECDSA, they swapped the signature’s s value for its mathematically equivalent n − s. For RSA, they dropped an optional NULL parameter. In both cases Java blocked the listed certificate but trusted the re-encoded one, because its fingerprint was different.
The official fix covers this case. The upstream OpenJDK change adds the same 16 certificates and generates the blocklist so that alternative encodings are matched too. A hand-edited file with only the 16 original fingerprints doesn’t have that protection. The 48-line list above adds the two known re-encodings, which are exactly the ones Sonatype used, and testing on Temurin showed Java does accept the NULL-toggled variants, so they’re worth blocking.
Even with all 48 lines, a hand-edited file only blocks the encodings someone has thought of, so treat it as the first layer and remove both affected roots as the second layer. In Sonatype’s tests, removing the relevant roots from the trust store rejected both re-encoded chains, and it’s the same approach as Corretto’s proposed fix for versions 11, 17, 21 and 25. The cost is low for most applications: browsers are dropping the emSign root anyway, so sites that chain to it have to move to another CA, and Chrome and Firefox haven’t trusted AAA Certificate Services for TLS for some time. Still check your outbound dependencies first. Revocation checking is an extra option if your network can reach the CAs’ CRL endpoints. Replace the workaround with a vendor build as soon as one is available.
Checklist
- Inventory every Java runtime you run: services, containers, CI runners and desktop tools. Note which trust store each one actually reads: its own
cacerts, the OS trust store, ajssecacertsfile, or a custom file set withjavax.net.ssl.trustStore. - Distro-packaged OpenJDK: update
ca-certificates, or on RHEL and UBI apply Red Hat’s workaround until a fixed package ships. - Oracle JDK and Azul Zulu: install the patched build, or use the vendor’s replacement block-list file in the meantime.
- Other standalone JDK builds: patch
blocked.certsnow, remove the emSign ECC and AAA Certificate Services roots, and watch for the vendor fix. - Restart JVMs, then verify against test hosts for both the emSign and the AAA chain.
- Once fixed builds ship, bump your base images, rerun the test hosts for both chains against the new build, and only then remove the workaround.
Sources
- Oracle Security Alert CVE-2026-91403
- NVD entry for CVE-2026-91403
- OpenJDK Vulnerability Advisory 2026/10/21
- Oracle guidance on distrusting the eMudhra intermediates
- eMudhra intermediate CA compromise: reporter’s incident page
- Mozilla bug 2083449
- Hands-on testing on OpenJDK and Temurin (lilting.ch)
- Sonatype: The limits of fingerprint blocklists
- SafeDep: eMudhra CA key compromise response guide
- Corretto pull requests removing emSign ECC Root CA – G3 and AAA Certificate Services: Corretto 11, 17, 21 and 25
- The Hacker News: fixes across browsers and software
- SOCRadar: incident timeline and root distrust
- Azul Zulu out-of-cycle release notes, October 21, 2026
- Azul: workaround for the eMudhra CA certificate compromise
- ctlogs.dev: eMudhra intermediate CA compromise
- BellSoft: distrusting compromised eMudhra intermediates in Java
- Safeguard: check and fix cacerts and custom trust stores
- gominimal/pkgs #949: JDK fix with the 48-fingerprint list
- Red Hat RHSB-2026-012: eMudhra certificate compromise
- Adoptium: October 2026 Temurin release status
- Cyber Kendra: Oracle Java emergency fix for eMudhra CAs
Credits
This post was written with the help of Claude, Anthropic’s AI assistant. Thanks to Maciej Pyszka, who worked out the blocked.certs workaround described above together with Claude.
