Resposta curta. Desde março de 2024, o CA/Browser Forum exige que as CAs publiquem CRLs e torna o OCSP opcional. A Let’s Encrypt removeu as URLs de OCSP dos seus certificados em maio de 2025 e desligou seus respondedores em agosto de 2025. Os navegadores não perguntam mais às CAs sobre cada certificado. O Firefox consulta um filtro CRLite local, o Chrome consulta o CRLSet distribuído a ele, e a Apple usa sua própria lista agregada. A maioria das bibliotecas e ferramentas de linha de comando (Java, .NET, Go, Python, Node.js, curl) não verifica revogação alguma por padrão. Nos nossos testes, todas aceitaram um certificado revogado da Let’s Encrypt. Se seu cliente precisa rejeitar certificados revogados, ative explicitamente a verificação de CRL e prepare-se para certificados com vida útil curta. É para lá que o setor está indo, de qualquer forma.
Por que a revogação precisou ser repensada
Um certificado pode ser revogado antes de expirar, em geral porque a chave vazou ou porque ele foi emitido por engano. As duas formas clássicas de avisar os clientes eram:
- CRL (Certificate Revocation List, lista de certificados revogados, RFC 5280): a CA publica uma lista assinada com os números de série revogados. O certificado aponta para ela na extensão CRL Distribution Points.
- OCSP (RFC 6960): o cliente pergunta ao respondedor da CA sobre um certificado e recebe uma resposta assinada: “good”, “revoked” ou “unknown”. A URL fica na extensão Authority Information Access.
Na web, os dois tinham problemas. As CRLs podiam ser grandes. O OCSP revelava à CA cada site que o usuário visitava, aumentava a latência, e os navegadores precisavam seguir em frente sem resposta (“soft-fail”) quando o respondedor estava inacessível. Um atacante capaz de bloquear a requisição OCSP torna a verificação inútil. O OCSP stapling resolveu o problema de privacidade fazendo o próprio servidor buscar a resposta e anexá-la, mas nunca se tornou universal. O Must-Staple, uma flag no certificado que exige uma resposta entregue por stapling, teve pouco suporte nos navegadores.
O que as regras dizem agora
A votação SC-063 (“Tornar o OCSP opcional, exigir CRLs e incentivar a automação”, em vigor desde 15 de março de 2024) mudou os Baseline Requirements:
- As CRLs são obrigatórias. Uma CA deve publicar uma CRL completa ou fragmentada (sharded) em até 24 horas depois de emitir seu primeiro certificado. Ela deve atualizar a CRL pelo menos a cada 7 dias se todos os seus certificados trouxerem uma URL de OCSP, e a cada 4 dias caso contrário, além de atualizá-la em até 24 horas depois de revogar um certificado (§4.9.7). Para certificados de assinante, o
nextUpdatepode ficar no máximo 10 dias depois dothisUpdate(§7.2). - O OCSP é opcional. Se um certificado tem uma URL de OCSP, o respondedor deve responder, e as respostas devem ter validade de 8 horas a 10 dias (§4.9.9). Um certificado sem URL de OCSP deve trazer um CRL Distribution Point (§7.1.2.11.2).
- Certificados de curta duração dispensam informações de revogação. Um “Short-lived Subscriber Certificate” vale por no máximo 7 dias se for emitido a partir de 15 de março de 2026 (antes, 10 dias). A CA pode oferecer a revogação desse certificado, e o CRL Distribution Point é opcional.
- Prazos de revogação. 24 horas para comprometimento da chave e casos semelhantes, 5 dias para os demais (§4.9.1.1).
Em seguida, a Let’s Encrypt abandonou o OCSP por completo, “principalmente porque ele representa um risco considerável à privacidade na internet”:
- 30 de janeiro de 2025: novas solicitações com Must-Staple falham.
- 7 de maio de 2025: as URLs de OCSP são removidas dos novos certificados, que passam a trazer URLs de CRL.
- 6 de agosto de 2025: os respondedores OCSP são desligados.
O que os certificados trazem hoje
Verificar alguns sites em 20 de outubro de 2026 em busca de uma URL de OCSP, uma URL de CRL e uma resposta OCSP por stapling mostra um quadro misto:
letsencrypt.org Let's Encrypt OCSP=- CRL=http://ye2.c.lencr.org/96.crl
staple: OCSP response: no response sent
www.google.com Google Trust Services OCSP=- CRL=http://c.pki.goog/we2/xuzt3PU9F_w.crl
staple: OCSP response: no response sent
github.com Sectigo Limited OCSP=http://ocsp.sectigo.com CRL=-
staple: OCSP response: no response sent
www.digicert.com DigiCert Inc OCSP=http://ocsp.digicert.com CRL=http://crl3.digicert.com/DigiCertEVRSACAG2.crl
staple: OCSP Response Status: successful (0x0)
www.microsoft.com Microsoft Corporation OCSP=http://oneocsp.microsoft.com/ocsp CRL=http://www.microsoft.com/pkiops/crl/partition/Microsoft%20TLS%20G2%20RSA%20CA%20OCSP%2004_Partition00093.crl
staple: OCSP Response Status: successful (0x0)
www.amazon.com Amazon OCSP=http://ocsp.r2m04.amazontrust.com CRL=http://crl.r2m04.amazontrust.com/r2m04.crl
staple: OCSP Response Status: successful (0x0)
A Let’s Encrypt e a Google Trust Services emitem certificados só com CRL. O certificado do GitHub, emitido pela Sectigo, é o caso inverso: só OCSP, o que os BR permitem. Um cliente que aceita apenas um dos dois métodos não consegue verificar todos esses certificados.
As CRLs não são pequenas, mas têm um tamanho administrável:
http://yr1.c.lencr.org/46.crl 192226 bytes 5094 entries Oct 20 12:26:45 2026 GMT -> Oct 29 12:26:44 2026 GMT
http://c.pki.goog/we2/xuzt3PU9F_w.crl 87562 bytes 2456 entries Oct 20 11:12:29 2026 GMT -> Oct 30 10:12:28 2026 GMT
http://crl3.digicert.com/DigiCertEVRSACAG2.crl 635286 bytes 17091 entries Oct 20 06:24:08 2026 GMT -> Oct 27 06:24:08 2026 GMT
A Let’s Encrypt fragmenta suas CRLs: cada certificado aponta para um entre muitos arquivos numerados, e a extensão Issuing Distribution Point da CRL identifica esse fragmento. O decodificador de CRL lê qualquer um desses arquivos, confere a assinatura da CRL com o emissor e informa se um determinado certificado está nela.
Como os navegadores verificam a revogação
Nenhum dos principais navegadores envia mais requisições OCSP para um certificado comum:
- Firefox: CRLite. O Firefox baixa uma codificação compactada de todos os certificados revogados que aparecem nos logs CT, atualiza esses dados a cada 12 horas e os consulta localmente. Segundo a Mozilla, isso representa cerca de 300 kB de dados por dia, em média. O CRLite está ativado para todos os usuários de desktop desde o Firefox 137. O Firefox 142 deixou de usar OCSP para certificados com validação de domínio, e o Firefox para Android adotou o CRLite na versão 145.
- Chrome: CRLSets. O Chrome distribui uma lista montada a partir das CRLs das CAs, mas só com “um subconjunto dos certificados identificados como revogados”, e “verificações online (isto é, OCSP e CRL) geralmente não são feitas pelo Chrome” (Chromium). No nosso teste, o Chromium 156 carregou
https://revoked-isrgrootx1.letsencrypt.org/com HTTP 200. - Apple: uma lista agregada. A Apple coleta dados de revogação das CAs e os distribui aos dispositivos. Em dezembro de 2025, o suporte técnico para desenvolvedores da Apple explicou que os certificados “só vão parar na lista de ‘malcomportados’ da Apple” quando são revogados por motivos como comprometimento da chave, e que não há uma verificação OCSP secundária para certificados da Let’s Encrypt. Por isso, o Safari ainda pode aceitar um certificado revogado por um motivo comum.
Na prática, isso significa que revogar um certificado não funciona como um botão de emergência rápido nos navegadores. O Firefox recebe as revogações pelas atualizações do CRLite a cada 12 horas. O Chrome e o Safari podem nunca chegar a bloquear uma revogação comum. O limite real para uma chave vazada é a vida útil restante do certificado, e esse é um dos motivos da mudança para certificados de 47 dias.
O que bibliotecas e ferramentas verificam por padrão
Em 20 de outubro de 2026, cada cliente abaixo se conectou a https://revoked-isrgrootx1.letsencrypt.org/ (revogado em 7 de outubro de 2026) e a https://valid-isrgrootx1.letsencrypt.org/. O certificado revogado tem uma URL de CRL e nenhuma URL de OCSP.
| Cliente | Padrão no site revogado | Verificação de revogação que funcionou |
|---|---|---|
| Java 25 (JSSE) | HTTP 200 | -Dcom.sun.net.ssl.checkRevocation=true -Dcom.sun.security.enableCRLDP=true |
.NET 10 HttpClient | HTTP 200 | SslOptions.CertificateRevocationCheckMode = X509RevocationMode.Online |
Go 1.27 crypto/tls | 200 OK | Verificação própria em tls.Config.VerifyConnection |
Python 3.13 ssl | handshake ok | VERIFY_CRL_CHECK_LEAF e a CRL carregada no contexto |
Node.js 24 tls | handshake ok | Opção crl com uma CRL por elemento do array, para cada nível da cadeia |
| curl 8.14 (OpenSSL) | HTTP 200 | --crlfile com as CRLs de cada nível da cadeia |
| Chromium 156 | HTTP 200 | Nenhuma (só o CRLSet) |
Os detalhes de cada cliente vêm a seguir.
Java
O JSSE não verifica revogação a menos que com.sun.net.ssl.checkRevocation seja true. Mesmo assim, ele usa só OCSP, a não ser que os CRL Distribution Points também estejam habilitados, e é por isso que um certificado da Let’s Encrypt falha como desconhecido, e não como revogado:
--- 1. default
HTTP 200
--- 2. -Dcom.sun.net.ssl.checkRevocation=true
javax.net.ssl.SSLHandshakeException: (certificate_unknown) PKIX path validation failed: java.security.cert.CertPathValidatorException: Could not determine revocation status
--- 3. checkRevocation + -Dcom.sun.security.enableCRLDP=true (revoked site)
javax.net.ssl.SSLHandshakeException: (certificate_revoked) PKIX path validation failed: java.security.cert.CertPathValidatorException: Certificate has been revoked, reason: UNSPECIFIED, revocation date: Wed Oct 07 18:37:19 UTC 2026, authority: CN=YR1, O=Let's Encrypt, C=US, extension OIDs: []
--- 4. same, valid site
HTTP 200
Com a verificação ativada, o validador PKIX rejeita o certificado (hard-fail) quando não consegue determinar um status. Isso é seguro, mas aí uma queda do servidor de CRL vira uma queda do seu serviço. O java.security.cert.PKIXRevocationChecker permite escolher, por conexão, a ordem entre OCSP e CRL e as opções de soft-fail.
.NET
O HttpClient com SocketsHttpHandler não verifica revogação por padrão. Definir o modo como Online faz o .NET buscar por conta própria a CRL ou a resposta OCSP. No Linux, ele faz isso com uma implementação própria sobre o OpenSSL:
var handler = new SocketsHttpHandler();
handler.SslOptions.CertificateRevocationCheckMode = X509RevocationMode.Online;
using var client = new HttpClient(handler);
https://revoked-isrgrootx1.letsencrypt.org/ revocation=default -> 200
https://revoked-isrgrootx1.letsencrypt.org/ revocation=Online -> The remote certificate is invalid because of errors in the certificate chain: Revoked
https://valid-isrgrootx1.letsencrypt.org/ revocation=default -> 200
https://valid-isrgrootx1.letsencrypt.org/ revocation=Online -> 200
Go
O crypto/tls valida a cadeia e o nome e nunca verifica a revogação. Se você precisar disso, confira a CRL por conta própria depois da verificação. x509.ParseRevocationList e CheckSignatureFrom fazem a parte difícil:
func checkCRL(cs tls.ConnectionState) error {
chain := cs.VerifiedChains[0]
leaf, issuer := chain[0], chain[1]
if len(leaf.CRLDistributionPoints) == 0 {
return errors.New("certificate has no CRL distribution point")
}
resp, err := http.Get(leaf.CRLDistributionPoints[0])
if err != nil {
return err
}
defer resp.Body.Close()
der, err := io.ReadAll(io.LimitReader(resp.Body, 64<<20))
if err != nil {
return err
}
crl, err := x509.ParseRevocationList(der)
if err != nil {
return err
}
if err := crl.CheckSignatureFrom(issuer); err != nil {
return fmt.Errorf("CRL signature: %w", err)
}
if time.Now().After(crl.NextUpdate) {
return errors.New("CRL is past its nextUpdate")
}
for _, entry := range crl.RevokedCertificateEntries {
if entry.SerialNumber.Cmp(leaf.SerialNumber) == 0 {
return fmt.Errorf("certificate %X revoked at %s", leaf.SerialNumber, entry.RevocationTime.UTC())
}
}
return nil
}
// client := &http.Client{Transport: &http.Transport{TLSClientConfig: &tls.Config{VerifyConnection: checkCRL}}}
https://revoked-isrgrootx1.letsencrypt.org/ -> 200 OK
https://revoked-isrgrootx1.letsencrypt.org/ -> Get "https://revoked-isrgrootx1.letsencrypt.org/": certificate 67E51010C975E496C8EB800F3EF1BAB3F2B revoked at 2026-10-07 18:37:19 +0000 UTC
https://valid-isrgrootx1.letsencrypt.org/ -> 200 OK
https://valid-isrgrootx1.letsencrypt.org/ -> 200 OK
O exemplo verifica só o certificado folha e baixa a CRL a cada handshake. Em produção, mantenha cada CRL em cache até o NextUpdate dela e decida o que acontece quando o servidor de CRL estiver fora do ar.
Python, Node.js e curl
Os três usam a verificação de CRL do OpenSSL e esperam que você forneça as CRLs. Eles nunca as baixam:
python 3.13.5 default: handshake ok, TLSv1.3
python 3.13.5 VERIFY_CRL_CHECK_LEAF: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate revoked (_ssl.c:1029)
node v24.22.0 default: handshake ok
node v24.22.0 crl: UNABLE_TO_GET_CRL unable to get certificate CRL
O ssl.VERIFY_CRL_CHECK_LEAF do Python verifica só o certificado folha, então basta carregar a CRL dele com ctx.load_verify_locations(cafile=...). O Node.js e o curl verificam cada certificado da cadeia, então uma CRL só do certificado folha resulta em UNABLE_TO_GET_CRL (Node) ou unable to get certificate CRL (curl) mesmo em um site válido. Forneça a CRL de cada certificado da cadeia. No Node.js 24, passe as CRLs como um array com uma string PEM por CRL. No nosso teste, um único buffer com três CRLs concatenadas ainda falhou com UNABLE_TO_GET_CRL:
revoked-isrgrootx1.letsencrypt.org (one buffer): UNABLE_TO_GET_CRL unable to get certificate CRL
revoked-isrgrootx1.letsencrypt.org (array): CERT_REVOKED certificate revoked
valid-isrgrootx1.letsencrypt.org (one buffer): UNABLE_TO_GET_CRL unable to get certificate CRL
valid-isrgrootx1.letsencrypt.org (array): handshake ok
As duas opções do curl se comportam de formas diferentes. A opção --cert-status exige uma resposta OCSP entregue por stapling, então falha em todo servidor que não faz stapling, incluindo todos os sites da Let’s Encrypt. A opção --crlfile funciona com um arquivo que contém as CRLs de toda a cadeia:
$ curl -s -o /dev/null -w "HTTP %{http_code}\n" https://revoked-isrgrootx1.letsencrypt.org/
HTTP 200
$ curl -sS -o /dev/null --cert-status https://revoked-isrgrootx1.letsencrypt.org/
curl: (91) No OCSP response received
$ curl -sS -o /dev/null --crlfile revoked-chain-crls.pem https://revoked-isrgrootx1.letsencrypt.org/
curl: (60) SSL certificate problem: certificate revoked
$ curl -s -o /dev/null -w "HTTP %{http_code}\n" --crlfile valid-chain-crls.pem https://valid-isrgrootx1.letsencrypt.org/
HTTP 200
$ curl -sS -o /dev/null --crlfile leaf-crl-only.pem https://valid-isrgrootx1.letsencrypt.org/
curl: (60) SSL certificate problem: unable to get certificate CRL
Este script reúne a CRL de cada certificado que um servidor envia:
#!/bin/bash
host="$1"; out="$2"
dir=$(mktemp -d)
openssl s_client -connect "$host:443" -servername "$host" -showcerts </dev/null 2>/dev/null \
| awk -v d="$dir" '/BEGIN CERTIFICATE/{n++} n>0{print > (d "/cert" n ".pem")}'
: > "$out"
for cert in "$dir"/cert*.pem; do
url=$(openssl x509 -in "$cert" -noout -ext crlDistributionPoints 2>/dev/null | grep -o 'http[^ ]*' | head -1)
[ -n "$url" ] && curl -s "$url" | openssl crl -inform DER >> "$out"
done
rm -r "$dir"
echo "$host: $(grep -c 'BEGIN X509 CRL' "$out") CRLs"
Como verificar um certificado manualmente
Com o OpenSSL, você pode ver onde fica o status de um certificado e verificá-lo diretamente. Comece pelas extensões:
$ openssl x509 -in leaf.pem -noout -ext crlDistributionPoints,authorityInfoAccess
Authority Information Access:
CA Issuers - URI:http://yr1.i.lencr.org/
X509v3 CRL Distribution Points:
Full Name:
URI:http://yr1.c.lencr.org/44.crl
Depois, baixe a CRL e verifique o certificado com ela. A opção -untrusted fornece os intermediários que o servidor enviou:
$ curl -s -o crl.der http://yr1.c.lencr.org/44.crl
$ openssl crl -inform DER -in crl.der -out crl.pem
$ openssl verify -crl_check -CRLfile crl.pem -untrusted chain.pem leaf.pem
CN=revoked-isrgrootx1.letsencrypt.org
error 23 at 0 depth lookup: certificate revoked
error leaf.pem: verification failed
$ openssl crl -in crl.pem -noout -text | grep -A1 "Serial Number: 067E51010C975E496C8EB800F3EF1BAB3F2B"
Serial Number: 067E51010C975E496C8EB800F3EF1BAB3F2B
Revocation Date: Oct 7 18:37:19 2026 GMT
Para uma CA que ainda mantém OCSP, pergunte diretamente ao respondedor ou examine a resposta entregue por stapling:
$ openssl ocsp -issuer issuer.pem -cert leaf.pem -url http://ocsp.digicert.com -resp_text -noverify
OCSP Response Status: successful (0x0)
Cert Status: good
This Update: Oct 19 22:09:00 2026 GMT
Next Update: Oct 26 21:09:00 2026 GMT
leaf.pem: good
This Update: Oct 19 22:09:00 2026 GMT
Next Update: Oct 26 21:09:00 2026 GMT
$ openssl s_client -connect www.digicert.com:443 -servername www.digicert.com -status </dev/null
OCSP Response Status: successful (0x0)
Cert Status: good
A opção -noverify pula a verificação da assinatura da resposta, o que serve para uma olhada rápida, mas não para tomar uma decisão. O decodificador OCSP analisa requisições e respostas, verifica a assinatura e a autorização do respondedor e pode consultar um respondedor por você.
O que fazer no seu serviço
- Decida se você precisa mesmo de verificação de revogação. Para chamadas de saída a APIs públicas, o modelo dos navegadores (vidas úteis curtas, CT, resposta a incidentes por parte das CAs) costuma bastar. Para conexões de alto valor, como callbacks de pagamento, mTLS entre organizações ou assinatura de código e de documentos, verifique a revogação explicitamente.
- Priorize o suporte a CRLs. As CAs públicas são obrigadas a publicá-las, e algumas não mantêm mais OCSP. Um cliente que só faz OCSP não vai conseguir decidir nada sobre certificados da Let’s Encrypt e da Google Trust Services.
- Mantenha as CRLs em cache e atualize-as no ritmo delas. Baixe cada CRL uma vez, guarde-a até o
nextUpdatee atualize-a em segundo plano, para que um handshake TLS nunca espere por um download. - Escolha entre fail-open e fail-closed de forma consciente. O fail-closed transforma um problema na CDN de uma CA em uma queda do seu serviço. O fail-open torna a verificação opcional para qualquer um que consiga bloquear o download da CRL. Registre em log os dois desfechos.
- Elimine dependências de Must-Staple e de OCSP stapling. A Let’s Encrypt rejeita solicitações com Must-Staple, e o stapling só ajuda com CAs que ainda mantêm OCSP.
- Na PKI privada, quem decide o projeto é você. Publique CRLs com um
nextUpdatecurto, ou emita certificados de curta duração e dispense a revogação, como os BR agora permitem para certificados de 7 dias ou menos.
Fontes
- CA/Browser Forum, Baseline Requirements v2.3.1: §4.9.1.1 (prazos de revogação), §4.9.7 (frequência das CRLs), §4.9.9 (OCSP), §7.1.2.11.2 (pontos de distribuição de CRL), §7.2 (perfil da CRL), definição de Short-lived Subscriber Certificate. Votação SC-063.
- RFC 5280 (CRLs) e RFC 6960 (OCSP).
- Let’s Encrypt, Fim do suporte ao OCSP em 2025.
- Mozilla, CRLite: verificação de revogação de certificados rápida, privada e abrangente no Firefox (agosto de 2025), e as notas de versão do Firefox para Android 145.
- Chromium, CRLSets.
- Apple Developer Forums, tópico 808875 (dezembro de 2025).
Os testes rodaram em 20 de outubro de 2026 em node:24.22.0-trixie (OpenSSL 3.5.7, curl 8.14.1, Node.js 24.22.0, Python 3.13.5), eclipse-temurin:25.0.4.1_1-jdk-noble, golang:1.27.3-trixie, mcr.microsoft.com/dotnet/sdk:10.0.402-noble e mcr.microsoft.com/playwright:v1.64.1-noble (Chromium 156).