Skip to content
audiotale.net
Sign in
GuidesGuide

How Java decides which certificates to trust: cacerts, keytool and revocation

A step-by-step guide to the Java trust store, the keytool commands to inspect and edit it, why revocation is off by default, and a routine for the next CA compromise.

audiotale.net team

· 7 min read

Written by AI from the sources linked below. How we use AI

On this page
  1. In short
  2. Why this matters right now
  3. Step 1: What a trust store is
  4. Step 2: Look inside cacerts
  5. Step 3: Revocation is off by default
  6. Step 4: Signed code uses the same machinery
  7. Step 5: The block list
  8. Step 6: A repeatable routine
  9. Common questions
  10. Further reading
  11. Sources

In short

A Java program decides which websites and signers to trust from a file shipped inside the runtime, usually called cacerts, unless you point it at a different file. Out of the box Java does not check whether a certificate has been revoked, so the contents of that file, and the runtime's own block list, are what protect you when a certificate authority is compromised. You can list the file with keytool -list -cacerts, remove an entry with keytool -delete -cacerts -alias <name>, point an application at another file with -Djavax.net.ssl.trustStore, and turn on revocation checking with two system properties. This guide shows how each piece works, using this week's eMudhra incident as the worked example.

Why this matters right now

On 21 and 24 October 2026 OpenJDK and Oracle issued two out-of-cycle fixes, CVE-2026-91403 and CVE-2026-114820, after eight eMudhra intermediate certificates were compromised. Our news article, Java eMudhra fixes: what to do, lists the affected builds and the steps. This guide explains the machinery behind those steps so you can handle the next incident without a checklist. For the web-wide view of how trust and revocation work, see how TLS certificate trust and revocation work.

Step 1: What a trust store is

When a Java client connects over TLS, the server presents a chain of certificates: the server's own, one or more intermediates, and a root. The client builds a path from the server's certificate up to a certificate it already trusts. Those trusted certificates are the trust anchors, and Java keeps them in a trust store.

Oracle's JSSE reference guide describes how the default trust store is chosen. If the system property javax.net.ssl.trustStore is set, Java uses that file. If it is not set, Java uses java-home/lib/security/jssecacerts if that file exists, and otherwise java-home/lib/security/cacerts. If the property names a file that does not exist, the guide says a default trust manager with an empty keystore is created, which means nothing is trusted. If a password system property, javax.net.ssl.trustStorePassword, is set, it is used to check the integrity of the file before opening it.

Two consequences follow:

  • Every Java installation has its own copy of the roots. Updating your operating system's certificate store does not change a runtime that ships its own cacerts. OpenJDK notes that some Linux distributions wire their Java packages to the system certificates (it names Arch Linux, Fedora, Gentoo, Oracle Linux and Red Hat Enterprise Linux) while FreeBSD and Homebrew packages do not.
  • An application can override the default entirely with its own trust store, so a "Java is patched" statement says nothing about an app that carries a custom file.

Step 2: Look inside cacerts

The keytool utility that ships with the JDK manages trust stores. Oracle's documentation says you can list the default certificates on Linux, macOS and Windows with:

keytool -list -cacerts

It will ask for the keystore password. The documentation states the initial password of the cacerts file is changeit, and that administrators should change the password and the default access permission when installing the SDK. Treat that as a reason to restrict who can edit the file on your servers.

Each entry has an alias, such as the emsignrootcag1 [jdk] alias that OpenJDK's eMudhra page tells you to delete. Piping the listing through a text search for a name is the quickest way to see whether a given root is present.

The same guide has a warning worth taking seriously: because you trust every CA in cacerts to vouch for other entities, you should manage the file carefully, it should contain only certificates of the authorities you trust, and verifying its contents is your responsibility. To remove an untrusted certificate, the guide says to use the -delete command of keytool with the -cacerts option, for example:

keytool -delete -cacerts -alias "emsignrootcag1 [jdk]"

That is exactly the form OpenJDK uses in its workaround for JDK 11 and later. For JDK 8 it uses the -keystore option with the path $JDK_HOME/jre/lib/security/cacerts. Back up the file first and restart any running Java process afterwards, since a live JVM has already loaded its trust anchors.

Step 3: Revocation is off by default

A certificate authority can revoke a certificate it issued, and the revocation travels in a certificate revocation list (CRL) or through OCSP, an online status check. Browsers usually receive distrust decisions from their vendors. Java does not work that way. Azul's statement on the eMudhra incident says Java runtimes do not receive revocation data automatically and do not check revocation by default, so the only dependable fix is to change what the runtime trusts.

Oracle's documentation backs this up in detail:

  • In the JSSE reference guide, the system property com.sun.net.ssl.checkRevocation has a default of false. It also notes that you must enable revocation checking to enable client-driven OCSP.
  • Setting it to true requires that the certification path implementation can find revocation information on its own. The guide says the PKIX provider can do this in many cases but needs the system property com.sun.security.enableCRLDP set to true.
  • The PKI programmer's guide says support for the CRL Distribution Points extension is available but disabled by default for compatibility, and can be enabled by setting com.sun.security.enableCRLDP to true.

OpenJDK's eMudhra page uses exactly these two switches as a temporary option: add -Dcom.sun.net.ssl.checkRevocation=true -Dcom.sun.security.enableCRLDP=true to the application's java command line.

Note the limits of this approach. Revocation checking needs network access to the CA's revocation endpoints and adds a dependency on them, and Oracle's guide ties CRL lookups to the certificate carrying a distribution-point extension. And it only helps if the compromised authority actually published revocations. For a quick containment step, editing the trust store is more certain; for a long-lived service, enabling revocation is a permanent improvement worth testing in staging.

Step 4: Signed code uses the same machinery

Trust decisions are not only about HTTPS. Signed JAR files are verified against certificates too. OpenJDK says that on JDK 17 and later you can check a signed file for revocation with:

jarsigner -verify -revcheck -strict <file.jar>

Run this over the signed libraries your build pulls in if the compromised authority was one your suppliers could have used. In the eMudhra case, eMudhra said only one of the eight intermediates was ever used in production and none issued an end-entity certificate, per Azul's summary, so the practical risk to signed code is low, but the check costs little.

Step 5: The block list

Alongside the trust store the JDK carries a block list. Azul's statement describes the fix for the eMudhra intermediates as a block list, lib/security/blocked.certs, that can reach a runtime in one of two ways: in a JDK update, or as a file placed by hand into each installed runtime followed by a restart. The update path is easier to audit; the manual path is how you handle a runtime you cannot update immediately, and it is the reason we recommend scripting any manual fix and recording which hosts received it. As we read Azul's description, the block list is separate from cacerts: a certificate can sit in the trust store and still be refused because it is on the block list.

Step 6: A repeatable routine

Use this as a checklist the next time a CA is compromised.

  1. Find every runtime. Hosts, build agents, container images, IDEs, and desktop applications that bundle their own JDK. OpenJDK provides CheckCerts.java, a program that works on JDK 8 and later and tells you whether a runtime is at risk in this incident.
  2. Prefer the vendor update. Read the release note for the CVE or bug ID. OpenJDK's page names JDK-8395690 and CVE-2026-114820 for this incident.
  3. If there is no update, edit the store or enable revocation checking as above, and record what you did.
  4. Handle distribution quirks. OpenJDK documents a long-standing bug in ca-certificates-java on Debian and derivatives (Devuan, Ubuntu): updating ca-certificates and ca-certificates-java is not enough, and the workaround is, as the superuser, rm -f /etc/ssl/certs/java/cacerts followed by update-ca-certificates --fresh.
  5. Rebuild images rather than patching running containers.
  6. Do not turn certificate verification off to make new errors go away. Cloudflare's guidance on the incident warns against exactly that.

Common questions

Is cacerts the same as the operating system's certificate store? Not on a standalone runtime. It is a separate file in the JDK. Some distribution packages link or regenerate it from the system store, which is why OpenJDK gives different instructions for different systems.

What is jssecacerts? According to the JSSE guide, a file with that name in the same folder is preferred over cacerts when it exists and no trust store property is set. If you find one, it is the file in charge.

Will deleting a root break my application? It will if a server you depend on chains to that root. Test first, and keep the backup you made so you can restore it.

Do I need to change the changeit password? Oracle's documentation says administrators should change it and tighten the file permission on install. Doing so is good hygiene, but a new password does not remove untrusted certificates; only edits or updates do.

Further reading

Sources

All claims above come from the pages linked in this article; docs references are to the Java SE 25 documentation, and behaviour on older releases may differ.

Written by

audiotale.net team

The official account of the people who run audiotale.net: announcements, conversation starters and the newsroom's drafts. Posts written with AI say so. Every other account here is a real person.