Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for DevOps Security & Hardening By James Joyner IV · · 9 min read

Security Error Guide: OpenSSL 'certificate revoked' (OCSP/CRL Revocation)

Quick answer

Fix 'certificate revoked' errors: check OCSP and CRL status with OpenSSL, confirm a real revocation vs. stale data, replace the cert, and harden revocation checking.

  • #security
  • #hardening
  • #troubleshooting
  • #errors
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

Overview

Certificate revocation lets a CA declare a certificate untrustworthy before it expires — after a key compromise, mis-issuance, or decommission. Clients check revocation via OCSP (Online Certificate Status Protocol) or a CRL (Certificate Revocation List). When a check returns revoked, a correctly configured client aborts the TLS handshake: continuing would trust a certificate the CA has explicitly disowned. This is a security control doing its job, but it also fires when revocation data is stale, the wrong certificate is deployed, or an OCSP responder is misbehaving.

The literal error from an OpenSSL verify or OCSP check:

verify error:num=23:certificate revoked
verify return code: 23 (certificate revoked)

An explicit OCSP query makes the status unambiguous:

Response verify OK
example.com.crt: revoked
	This Update: Jul  9 00:00:00 2026 GMT
	Next Update: Jul 16 00:00:00 2026 GMT
	Reason: keyCompromise
	Revocation Time: Jul  8 14:22:10 2026 GMT

And a browser/curl surfaces the same underlying condition:

curl: (35) OCSP response: certificate revoked

The Reason and Revocation Time fields tell you why and when — critical for deciding whether this is expected (you rotated a compromised key) or a surprise.

Symptoms

  • TLS clients reject a server certificate with certificate revoked / verify code 23.
  • openssl ocsp returns revoked with a revocation time and reason.
  • A previously working certificate starts failing without having expired.
  • Only revocation-checking clients fail; clients with revocation checks disabled still connect (a red flag, not a fix).
echo | openssl s_client -connect example.com:443 -status 2>/dev/null | grep -A4 'OCSP Response'
OCSP Response Status: successful (0x0)
Cert Status: revoked
Revocation Time: Jul  8 14:22:10 2026 GMT
Revocation Reason: keyCompromise (0x1)

Common Root Causes

1. The certificate was genuinely revoked

A CA revoked the cert after a reported key compromise, a re-issuance that superseded it, or an account/domain change. The deployed cert must be replaced.

openssl x509 -in server.crt -noout -serial
# then confirm that serial appears in the CRL / OCSP as revoked
serial=0A1B2C3D4E5F6071
Reason: keyCompromise

2. An old certificate is still deployed after rotation

A new certificate was issued and the old one revoked, but a server, load balancer, or CDN edge is still serving the old (now-revoked) cert.

echo | openssl s_client -connect example.com:443 2>/dev/null \
  | openssl x509 -noout -serial -dates
serial=0A1B2C3D4E5F6071
notBefore=Jan 10 ... notAfter=Apr 10 ...

If that serial is the revoked one, the wrong cert is live.

3. Wrong certificate in a chain or a reused key

A leaf whose key was reused from a revoked predecessor, or an intermediate that was revoked, taints the chain.

4. Stale or wrong CRL / OCSP cache

A client or proxy caches an old CRL/OCSP response, or an intermediate proxy injects a stale stapled response, showing revoked (or masking a revocation).

openssl crl -in cached.crl -noout -lastupdate -nextupdate
lastUpdate=Jun 01 ...  nextUpdate=Jun 08 ...   # expired CRL

5. OCSP responder or stapling misconfiguration

A server staples a revoked or invalid OCSP response, or the responder returns wrong data, causing clients to reject.

echo | openssl s_client -connect example.com:443 -status 2>/dev/null | grep 'Cert Status'

Diagnostic Workflow

Step 1: Capture the served certificate and its serial

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -out /tmp/served.crt
openssl x509 -in /tmp/served.crt -noout -serial -subject -dates

Step 2: Query OCSP directly for a definitive status

Extract the OCSP URI and the issuer, then ask the responder:

OCSP_URL=$(openssl x509 -in /tmp/served.crt -noout -ocsp_uri)
echo "$OCSP_URL"
openssl ocsp -issuer issuer.crt -cert /tmp/served.crt \
  -url "$OCSP_URL" -no_nonce -text 2>/dev/null | grep -A3 'Cert Status'
Cert Status: revoked
Revocation Time: Jul  8 14:22:10 2026 GMT
Revocation Reason: keyCompromise

Step 3: Cross-check against the CRL

CRL_URL=$(openssl x509 -in /tmp/served.crt -noout -text | grep -A4 'CRL Distribution' | grep URI | sed 's/.*URI://')
curl -s "$CRL_URL" -o /tmp/ca.crl
openssl crl -inform DER -in /tmp/ca.crl -noout -text | grep -A2 "$(openssl x509 -in /tmp/served.crt -noout -serial | cut -d= -f2)"

If the serial is listed, the revocation is real and CA-side.

Step 4: Confirm the CRL/OCSP data is fresh

openssl crl -inform DER -in /tmp/ca.crl -noout -lastupdate -nextupdate

If nextUpdate is in the past, you may be looking at stale data — refresh before concluding.

Step 5: Check what the server is stapling

echo | openssl s_client -connect example.com:443 -status 2>/dev/null | grep -A6 'OCSP Response'

A stapled revoked status points at the served cert; a “no response sent” points at a stapling config issue.

Example Root Cause Analysis

A partner API integration starts failing TLS with verify error:num=23:certificate revoked. The certificate is well within its validity window, so expiry is ruled out. Grabbing the served cert and querying OCSP is decisive:

echo | openssl s_client -connect api.partner.example:443 2>/dev/null | openssl x509 -out /tmp/served.crt
openssl ocsp -issuer issuer.crt -cert /tmp/served.crt \
  -url "$(openssl x509 -in /tmp/served.crt -noout -ocsp_uri)" -no_nonce 2>/dev/null | grep -A3 'Cert Status'
Cert Status: revoked
Revocation Time: Jul  8 14:22:10 2026 GMT
Revocation Reason: keyCompromise

The reason is keyCompromise with a revocation time from the previous day. The partner had rotated the certificate after a suspected private-key exposure and revoked the old one — but one node behind their load balancer was still serving the old, revoked cert. The revocation is entirely legitimate; the fix is not on the client side.

Resolution: the client should not bypass the check. The correct action is for the certificate owner to remove the revoked cert from every serving node and deploy the reissued one, then re-verify:

echo | openssl s_client -connect api.partner.example:443 -status 2>/dev/null \
  | grep -E 'Cert Status|serial'
Cert Status: good

Once every edge serves the reissued certificate, OCSP returns good and the handshake succeeds — without ever weakening revocation checking.

Prevention Best Practices

  • Treat a revoked status as authoritative: replace the certificate, never disable revocation checking to “fix” the connection.
  • Automate certificate rotation (ACME/cert-manager) and ensure the new cert is deployed to every node/edge before or as the old one is revoked, to avoid serving a revoked cert.
  • Enable OCSP stapling on servers and set ssl_stapling_verify on so clients get a fresh, verified status without hammering the responder.
  • Monitor your own certificates’ OCSP/CRL status proactively so you learn of a revocation from monitoring, not from a partner outage.
  • Keep intermediates and issuer certs available for OCSP checks, and alarm on CRLs whose nextUpdate has passed.
  • After any suspected key compromise, revoke and rotate; keep an inventory that maps serials to the systems serving them so cleanup is complete.

Quick Command Reference

# Capture the served certificate and its serial
echo | openssl s_client -connect host:443 -servername host 2>/dev/null | openssl x509 -out served.crt
openssl x509 -in served.crt -noout -serial -dates -ocsp_uri

# Direct OCSP query (definitive status + reason)
openssl ocsp -issuer issuer.crt -cert served.crt \
  -url "$(openssl x509 -in served.crt -noout -ocsp_uri)" -no_nonce -text | grep -A3 'Cert Status'

# Check the stapled OCSP response the server sends
echo | openssl s_client -connect host:443 -status 2>/dev/null | grep -A6 'OCSP Response'

# CRL freshness and serial lookup
openssl crl -inform DER -in ca.crl -noout -lastupdate -nextupdate
openssl crl -inform DER -in ca.crl -noout -text | grep -A2 <serial>

Conclusion

certificate revoked (verify code 23) means a CA has explicitly disowned the certificate and a revocation-checking client refused it — exactly what you want to happen to a compromised or superseded cert. Diagnose before reacting:

  1. A genuine revocation (keyCompromise, superseded) — replace the certificate.
  2. An old, revoked cert still served after rotation on some node/edge.
  3. A reused key or revoked intermediate tainting the chain.
  4. Stale CRL/OCSP cache data — refresh and re-check.
  5. A stapling/responder misconfiguration serving a bad status.

Capture the served cert, query OCSP and the CRL for a definitive Cert Status and reason, and fix the root cause by deploying a valid certificate everywhere — never by turning revocation checking off.

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.