How to check certificate revocation
Ask openssl to fetch the CRL named in the certificate and apply it: openssl s_client -connect host:443 -servername host -crl_download -crl_check </dev/null. A revoked certificate returns Verify return code: 23 (certificate revoked). The plain handshake without those two flags reports 0 (ok) for the same host.
Why check this
Revocation is the control you rely on after a key leaks, so it belongs in the incident drill and in the sign-off for any certificate rotation. The failure it prevents is silent: the certificate you retired stays usable, because most clients never ask whether it is still valid. Run the check on the old certificate after a rotation, not on the new one.
Prerequisites
- openssl 1.1.1 or later.
-crl_downloadfetches the CRL named inside the certificate. See the verification options manual. - curl for the manual route in steps 3 and 4.
- Outbound HTTP to the CA on port 80. CRL and OCSP endpoints are plain HTTP by design, so a proxy that blocks port 80 makes every check below time out.
Steps
- Step 1.
Run the ordinary handshake first, so the trap is visible.
openssl s_client -connect revoked.badssl.com:443 -servername revoked.badssl.com </dev/null 2>&1 | grep 'Verify return code'Verify return code: 0 (ok)The certificate on this host was revoked by its CA. openssl still reports
0 (ok), because revocation is off unless you ask for it. - Step 2.
Turn revocation on and repeat.
openssl s_client -connect revoked.badssl.com:443 -servername revoked.badssl.com -crl_download -crl_check </dev/null 2>&1 | grep -E 'verify error|Verify return code'verify error:num=23:certificate revoked Verify return code: 23 (certificate revoked) - Step 3.
Read the serial number and the CRL address out of the certificate, for the manual route.
openssl s_client -connect revoked.badssl.com:443 -servername revoked.badssl.com </dev/null 2>/dev/null | openssl x509 -noout -serial -ext crlDistributionPointsserial=05C391E061DE6588F670B613F061AEF4B3A1 X509v3 CRL Distribution Points: Full Name: URI:http://ye1.c.lencr.org/34.crl - Step 4.
Download that CRL and search it for the serial.
curl -s -o le.crl http://ye1.c.lencr.org/34.crl && openssl crl -inform DER -in le.crl -noout -text | grep -A1 05C391E061DE6588F670B613F061AEF4B3A1Serial Number: 05C391E061DE6588F670B613F061AEF4B3A1 Revocation Date: Jul 14 21:01:28 2026 GMTThe revocation date is the evidence an incident report needs.
-crl_downloadin step 2 does the same lookup and hides the date. - Step 5.
Check whether the CA offers OCSP at all before planning an OCSP query.
openssl s_client -connect revoked.badssl.com:443 -servername revoked.badssl.com </dev/null 2>/dev/null | openssl x509 -noout -text | grep -A2 'Authority Information Access'Authority Information Access: CA Issuers - URI:http://ye1.i.lencr.org/ X509v3 Subject Alternative Name:The block lists
CA Issuersand stops. There is noOCSP - URIline, so this certificate names no responder. Several large CAs removed that URI during 2025, which leaves the CRL as the only client-side route for the certificates they issue. - Step 6.
Confirm how your own HTTP client treats the same host, because the answer differs per TLS backend.
curl -sS -o /dev/null -w 'http=%{http_code}\n' https://revoked.badssl.com/http=200
How to read the result
| What you see | What it means | What to do |
| --- | --- | --- |
| Verify return code: 23 | The CA lists this serial as revoked | Take the host out of rotation. The certificate is dead to any client that checks |
| Verify return code: 0 (ok) without -crl_check | Nothing was checked | Rerun with -crl_download -crl_check before reporting a pass |
| Verify return code: 3 (unable to get certificate CRL) | No CRL reached openssl | Add -crl_download, or fetch the URL from step 3 by hand and read the status code |
| The serial appears in the CRL with a date | Confirmed revocation, with the timestamp | Paste the serial and the revocation date into the incident ticket |
| The AIA block holds no OCSP - URI line | This CA publishes no OCSP responder | Use the CRL. An OCSP query has no address to reach |
Common mistakes
What to check next
- How to check if OCSP stapling is enabled: the server-side half of revocation, which removes the client lookup entirely.
- How to check certificate chain: a CRL is signed by the issuer, so the chain has to resolve before the check means anything.
- How to check if a certificate is self-signed: a self-signed certificate has no CA and no revocation path at all.
- How to check SSL certificate expiry: expiry is the other way a certificate stops being usable, and it is checked by every client.
- SSL certificate checker: reads the chain and the dates of a host without a local openssl build.
FAQ
How to check certificate revocation status from the command line?
Step 2 is the short answer: -crl_download -crl_check on openssl s_client. It fetches the CRL named in the certificate, applies it and prints code 23 when the serial is listed. Steps 3 and 4 show the same result with the revocation date attached.
How to check a certificate revocation list by hand?
Read the CRL Distribution Points extension, download the file, then parse it with openssl crl -inform DER -noout -text. Search for your serial number in uppercase hexadecimal. A hit prints the entry and the revocation date underneath it.
Why does openssl say ok for a revoked certificate?
Because s_client performs path and date validation only. Revocation costs a network round trip to the CA, so it is opt in. -crl_check on its own is not enough either: without -crl_download it returns code 3, unable to get certificate CRL.
Is OCSP better than a CRL for this check?
It was, and it is going away. Certificates from several large CAs no longer carry an OCSP URI, which step 5 shows on revoked.badssl.com. Where a responder still exists, an OCSP answer is fresher than a weekly CRL.
Does revoking a certificate stop traffic immediately?
No. Clients that check at all cache the CRL or the OCSP answer until its next update, and many clients do not check. Rotate the certificate and drop the old key from the server rather than relying on revocation alone.
Verified
Verified by Maks Vernyopenssl 3.1.1curl 8.21.0
Each output block is what the command above it printed on that date, on the host named in the step. Figures read from a live site move between runs. Compare the shape of the answer rather than the digits, and see the methodology for how a page is re-verified.
Related on this site
intermediate8 minpublished updated Maks Verny