Voltar
2026/10/23
Em 20 de outubro de 2026, tornou-se público que as chaves privadas de oito autoridades certificadoras (CAs) intermediárias operadas pela eMudhra, uma CA indiana, podem ser recuperadas por qualquer pessoa. Os navegadores bloquearam os certificados no mesmo dia em que o problema foi relatado. Muitas aplicações Java, no entanto, ainda confiam neles hoje e continuarão confiando até que alguém atualize o JDK ou altere seu truststore.
Em 21 de outubro de 2026, a BellSoft publicou resultados de testes mostrando que muitos runtimes Java ainda aceitam esses certificados. Este artigo resume as conclusões deles, que confirmamos em nossos próprios testes, e explica por que o Java é afetado quando os navegadores não são, como verificar seus sistemas e o que fazer a respeito.
Principais pontos
- Oito chaves de CAs intermediárias da eMudhra foram comprometidas. Quem tiver uma delas pode emitir um certificado para qualquer hostname, e um cliente que confia na cadeia vai aceitá-lo.
- Os navegadores as bloqueiam, mas o Java usa seu próprio truststore e, por padrão, não verifica nem a revogação nem o Certificate Transparency.
- Builds do JDK de vários fornecedores ainda confiam em algumas ou em todas as cadeias afetadas, inclusive em imagens de contêiner.
- Até que seu fornecedor disponibilize um JDK corrigido, remova as duas raízes afetadas do truststore, depois de testar. A verificação de revogação é uma segunda opção.
O que aconteceu
A eMudhra gerou incorretamente as chaves privadas de oito de seus certificados de CA intermediária, de modo que qualquer pessoa pode recuperá-las a partir dos certificados públicos. Isso é possível desde que as intermediárias foram emitidas, em abril de 2025.
Em 17 de outubro de 2026, a pessoa que relatou o problema o comprovou assinando a mensagem “We have a problem here” com cada uma das oito chaves e enviando as assinaturas aos programas de raízes dos navegadores. Os detalhes se tornaram públicos em 20 de outubro.
- Seis intermediárias emitem certificados TLS: as CAs TLS DV, OV e EV da eMudhra, gerações G3B e G3C.
- Duas intermediárias emitem certificados de assinatura de código.
- Cada intermediária existe em duas versões: assinada por uma raiz emSign da eMudhra e com assinatura cruzada (cross-sign) da raiz
AAA Certificate Servicesda Sectigo. Em um truststore do JDK, as cadeias terminam em uma de duas raízes:emSign ECC Root CA - G3(por meio de uma assinatura cruzada) ouAAA Certificate Services.
O Firefox e o Chrome bloqueiam as intermediárias desde 17 de outubro, a Apple desde 19 de outubro e a Microsoft desde 20 de outubro. A eMudhra revogou as oito em 18 e 19 de outubro com o motivo CA_COMPROMISE. As distribuições Linux lançaram pacotes atualizados de certificados de CA.
Qual é o impacto
Quem tiver uma dessas chaves pode criar um certificado para qualquer hostname, como o do seu banco, do seu provedor de nuvem ou do seu próprio gateway de API. Um cliente que confia na cadeia vai aceitá-lo. Combinado com uma forma de interceptar o tráfego, por exemplo uma rede comprometida ou um registro DNS alterado, um invasor poderia:
- ler e alterar o tráfego entre uma aplicação Java e os serviços que ela chama, incluindo senhas, chaves de API e tokens;
- se passar por repositórios de pacotes, servidores de atualização ou APIs de parceiros;
- por meio das duas intermediárias de assinatura de código, assinar código que parece vir de um editor confiável.
As intermediárias nunca apareceram nos logs de Certificate Transparency (CT), portanto navegadores que exigem CT não poderiam ter sido atacados por meio delas. Ainda não se sabe se as chaves foram usadas contra clientes que não verificam CT. O Java é um desses clientes.
Por que o Java ainda confia nesses certificados
Mozilla, Google, Apple e Microsoft aplicaram o bloqueio por seus próprios canais, como OneCRL, CRLite e CRLSets. A implementação TLS padrão do JDK não lê nenhum deles. Três configurações padrão mantêm o Java exposto:
- Truststore próprio. A menos que uma aplicação defina
javax.net.ssl.trustStore, o Java confia nas raízes de$JAVA_HOME/lib/security/jssecacerts, se esse arquivo existir, e nas de$JAVA_HOME/lib/security/cacerts, caso contrário. Umcacertsque vem empacotado pelo fornecedor não recebe listas de bloqueio dos navegadores nem atualizações de CAs do sistema operacional. Ele só muda quando um administrador o edita ou quando uma atualização do JDK o substitui. - Sem verificação de revogação. O Java não verifica revogação a menos que você a habilite (
com.sun.net.ssl.checkRevocationé false por padrão), então a revogação feita pela CA é invisível para uma configuração padrão. - Sem Certificate Transparency. O JDK não exige CT, portanto a proteção que cobria os usuários de navegadores não se aplica.
A página de divulgação lista doze hosts de teste, um para cada combinação de intermediária e raiz. A BellSoft os testou no Linux em 21 de outubro, e repetimos o teste em 23 de outubro:
| Runtime testado | Hosts de teste considerados confiáveis |
|---|---|
| Liberica JDK 21.0.10 | 12 de 12 |
| Liberica JDK 8u504 (imagem de contêiner) | 12 de 12 |
| Liberica JDK 21.0.12.1 (imagem de contêiner) | 12 de 12 |
| Eclipse Temurin 25.0.4.1 | 6 de 12 (somente a raiz da eMudhra) |
| Eclipse Temurin 21.0.12.1 (imagem de contêiner, nosso teste) | 6 de 12 (somente a raiz da eMudhra) |
| Arch Linux OpenJDK 27 (repositório de CAs do sistema) | 6 de 12 (somente a raiz da eMudhra) |
A diferença está na raiz da Sectigo. A Mozilla já havia removido a AAA Certificate Services, e os truststores do Temurin e do Arch Linux são gerados a partir da lista da Mozilla, então apenas o caminho da eMudhra fica aberto. O truststore do Liberica JDK ainda contém essa raiz, então os dois caminhos ficam abertos.
Quais sistemas verificar
- JDKs avulsos, descompactados de um pacote do fornecedor ou instalados com o instalador do fornecedor. Eles usam seu próprio
cacerts. - Imagens de contêiner que incluem um JDK. Nas imagens testadas pela BellSoft, atualizar o pacote
ca-certificatesdo sistema operacional não alterou ocacertsdo JDK. Baixar uma imagem base mais recente também não ajudou: a imagem Liberica testada, de 21 de outubro, ainda confiava em todos os doze hosts de teste. - Aplicações com truststore próprio, definido com
javax.net.ssl.trustStore, na configuração de um servidor de aplicação ou dentro da própria aplicação. Verifique se ele contém as duas raízes. - OpenJDK empacotado pela distribuição. Verifique para onde
cacertsaponta. Se ele apontar para o repositório de CAs do sistema (no Arch Linux, é um symlink para/etc/ca-certificates/extracted/java-cacerts.jks), a atualização doca-certificatesda distribuição resolve o problema. A página de divulgação lista as versões corrigidas dos pacotes.
Como verificar seu JDK
Primeiro, procure as duas raízes no truststore. Os nomes de alias variam entre fornecedores (o Liberica JDK usa emsigneccrootcag3 [jdk], o Temurin usa cn_emsign_ecc_root_ca__g3,...), então pesquise pelo subject do certificado. Existem várias outras raízes emSign; apenas a emSign ECC Root CA - G3 é afetada. No JDK 9 e posteriores:
keytool -list -v -cacerts -storepass changeit | grep -E '^Alias name:|^Owner:' | grep -B1 -E '^Owner: CN=(emSign ECC Root CA - G3|AAA Certificate Services),'
O keytool do Java 8 não tem a opção -cacerts, e seu truststore fica em jre/:
keytool -list -v -keystore "$JAVA_HOME/jre/lib/security/cacerts" -storepass changeit | grep -E '^Alias name:|^Owner:' | grep -B1 -E '^Owner: CN=(emSign ECC Root CA - G3|AAA Certificate Services),'
Cada correspondência exibe o nome do alias seguido do subject do certificado. Anote os nomes de alias: você vai precisar deles para a correção.
Em seguida, teste conexões reais. Este pequeno programa se conecta aos doze hosts de teste e roda no Java 8 e em todas as versões posteriores:
import java.net.URI;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLHandshakeException;
public class Check {
public static void main(String[] args) {
for (String level : new String[]{"dv", "ov", "ev"})
for (String gen : new String[]{"g3b", "g3c"})
for (String via : new String[]{"", "-aaa"}) {
String host = level + "-" + gen + via + "-emudhra.we-have-a-problem.com";
try {
HttpsURLConnection c = (HttpsURLConnection) URI.create("https://" + host).toURL().openConnection();
c.setConnectTimeout(10000);
c.setReadTimeout(10000);
c.connect();
c.disconnect();
System.out.println("TRUSTED " + host);
} catch (SSLHandshakeException e) {
System.out.println("TLS_REJECTED " + host);
} catch (Exception e) {
System.out.println("ERROR " + host + " (" + e + ")");
}
}
}
}
No JDK 11 ou posterior, execute-o com java Check.java. No Java 8, ou onde apenas um JRE estiver instalado, compile-o primeiro com javac Check.java (em uma máquina com JDK, se necessário) e execute java Check. Uma linha TRUSTED significa que esse JDK aceita uma intermediária comprometida. ERROR significa que não foi possível alcançar o host, o que não prova nada, nem num sentido nem no outro. Execute a verificação com o mesmo JDK e as mesmas configurações de truststore da sua aplicação, inclusive dentro dos seus contêineres.
Como corrigir
1. Remova as duas raízes (recomendado até que um JDK corrigido seja lançado)
São as mesmas duas raízes nas quais a página de divulgação orienta os usuários de Linux e macOS a deixar de confiar. Execute os comandos como o usuário proprietário do JDK, com os nomes de alias que você encontrou na verificação. Por exemplo, no Liberica JDK:
keytool -delete -cacerts -storepass changeit -alias "comodoaaaca [jdk]"
keytool -delete -cacerts -storepass changeit -alias "emsigneccrootcag3 [jdk]"
No Java 8, substitua -cacerts por -keystore "$JAVA_HOME/jre/lib/security/cacerts". Se o seu truststore contiver apenas uma das duas raízes, como o do Temurin, exclua somente essa.
Se você não puder modificar a instalação do JDK, edite uma cópia e aponte a JVM para ela:
cp "$JAVA_HOME/lib/security/cacerts" ./trimmed-cacerts
keytool -delete -keystore ./trimmed-cacerts -storepass changeit -alias "comodoaaaca [jdk]"
keytool -delete -keystore ./trimmed-cacerts -storepass changeit -alias "emsigneccrootcag3 [jdk]"
java -Djavax.net.ssl.trustStore=./trimmed-cacerts -Djavax.net.ssl.trustStorePassword=changeit -jar app.jar
Em nossos testes, os dois métodos fizeram o Liberica JDK 8 e 21 rejeitar os doze hosts de teste, enquanto sites comuns como sectigo.com e github.com continuaram se conectando normalmente.
Para imagens de contêiner, exclua as raízes no momento do build, para que toda nova imagem já saia corrigida:
FROM bellsoft/liberica-runtime-container:jdk-21-musl
RUN keytool -delete -cacerts -storepass changeit -alias "comodoaaaca [jdk]" \
&& keytool -delete -cacerts -storepass changeit -alias "emsigneccrootcag3 [jdk]"
Imagens distroless e non-root precisam de duas alterações: elas não têm shell, então use a forma exec do RUN com um comando por linha; e elas rodam com um usuário sem privilégios, então mude para USER root para a edição e volte depois para o usuário normal da imagem.
Dica: Remover uma raiz tem um efeito mais amplo do que bloquear oito intermediárias. Um servidor legítimo cuja cadeia termine apenas em uma dessas raízes vai parar de funcionar. Teste os serviços que sua aplicação chama antes de implantar essa mudança e execute a verificação novamente após cada atualização do JDK, porque uma atualização ou reinstalação pode restaurar o cacerts original.
2. Ative a verificação de revogação (opcional)
A eMudhra revogou as oito intermediárias, então uma JVM que verifica revogação as rejeita sem nenhuma alteração no truststore. Habilite os pontos de distribuição de CRL e o OCSP:
echo 'ocsp.enable=true' > revocation.security
java -Dcom.sun.net.ssl.checkRevocation=true \
-Dcom.sun.security.enableCRLDP=true \
-Djava.security.properties=revocation.security \
-jar app.jar
Em nossos testes, isso rejeitou os doze hosts de teste no Liberica JDK 8 e 21 e no Temurin 21. No entanto, isso muda a forma como todo certificado é validado. A JVM faz consultas OCSP ou CRL durante a validação do caminho, e um handshake pode falhar quando o status de revogação não puder ser determinado. Antes de habilitar isso globalmente, teste se os responders são acessíveis a partir dos seus servidores, quanta latência eles adicionam e como o sistema se comporta em caso de falha. Use essa opção se você já trabalha com verificação de revogação, ou em conjunto com a remoção das raízes.
3. Atualize o JDK quando houver builds corrigidos
A BellSoft informou que está preparando atualizações do Liberica JDK que removem essas raízes. Acompanhe os avisos de segurança do fornecedor do seu JDK. Quando a atualização for lançada, leia as notas de versão para confirmar que ela cobre os certificados da eMudhra, instale-a, reconstrua suas imagens de contêiner e execute a verificação novamente. Um número de versão mais recente, por si só, não é prova.
Depois da correção: avalie sua exposição
As chaves puderam ser recuperadas por cerca de dezoito meses, então a correção fecha a porta, mas não diz se alguém passou por ela. Para sistemas que enviam credenciais ou dados sensíveis, procure nos logs de inspeção TLS, de proxy e de endpoints por certificados emitidos pelas oito intermediárias da eMudhra. Se encontrar algo suspeito, troque as credenciais afetadas.
No longo prazo, trate os truststores como dependências: saiba onde cada um está, quem o atualiza e com que rapidez uma alteração chega à produção. Este incidente mostra que uma atualização do navegador não basta quando seus servidores usam a própria cópia da lista de confiança.
Precisa de ajuda? A LOGIQ oferece suporte para OpenJDK e Linux, incluindo a aplicação de patches de segurança. Se você quiser ajuda para encontrar todos os JDKs e truststores do seu ambiente ou para implantar uma correção com segurança, fale conosco.
Leitura complementar
- eMudhra Intermediate CA Compromise: a página de divulgação, com os hosts de teste e as versões corrigidas dos pacotes
- BellSoft: Distrusting compromised eMudhra intermediates in Java
Global
Japan
Korea
China
Taiwan
Vietnam
Thailand
Indonesia
Spain
France
Germany
Egypt
Russia