Certificate Revocation Explained: CRL vs OCSP in the Real World

Certificate revocation sounds simple on paper. A certificate should stop being trusted before its expiration date, so the issuer marks it as revoked and clients reject it. In practice, it is messier than most administrators expect.

I ran into this the first time I had to replace a certificate after a private key leak. My assumption was straightforward: revoke the old certificate, deploy the new one, and move on. What I noticed instead was that revocation is only as useful as the client checking it, the CA publishing it, the network allowing it, and the browser deciding not to soft-fail. That is a long chain of “ifs.”

If you manage web servers, APIs, mail servers, load balancers, or internal PKI, you should understand what revocation is supposed to do and where it breaks down. This is the version I wish someone had explained to me earlier.

Why certificate revocation exists

A certificate normally stays valid until its Not After date. That can be 90 days for Let’s Encrypt, longer for many enterprise and private PKI deployments, or very short in tightly controlled environments. Revocation exists for the cases where waiting for natural expiry is not acceptable.

The usual reasons are familiar:

  • the private key was exposed
  • the certificate was issued to the wrong party
  • a hostname should no longer be covered
  • the organization changed ownership or legal status
  • the CA made an issuance error
  • malware or a compromised device enrolled a certificate it should never have had

In other words, revocation is the emergency brake.

The important practical lesson is this: revocation is not a replacement for short certificate lifetimes. I prefer short lifetimes because they reduce how long a bad certificate can remain useful even when revocation checks fail. Revocation is still necessary, but it is not strong enough to be your only safety mechanism.

For related background, see how TLS handshakes actually work and how certificate chains are built and validated.

Where revocation information lives in a certificate

A certificate can point clients to revocation data through X.509 extensions. The two that matter most are:

  • CRL Distribution Points (CDP): URLs where the client can download a Certificate Revocation List
  • Authority Information Access (AIA): often includes the OCSP responder URL

You can inspect both with OpenSSL:

openssl x509 -in server.crt -noout -text

Look for sections like these:

X509v3 CRL Distribution Points:
    Full Name:
      URI:http://crl.exampleca.com/exampleca.crl

Authority Information Access:
    OCSP - URI:http://ocsp.exampleca.com

If those extensions are absent, revocation checking becomes limited or impossible unless the client uses other mechanisms.

A quick way to inspect a live site is:

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -text

That is one of the commands I use when I want to see what the server is actually presenting rather than what someone thinks it is presenting. It also helps confirm that a replacement certificate really made it to the edge node or load balancer.

CRL: the original revocation mechanism

A Certificate Revocation List is exactly what the name suggests: a CA publishes a signed list of certificate serial numbers that should no longer be trusted.

The basic CRL flow looks like this:

  1. A CA revokes a certificate.
  2. The CA adds its serial number to the CRL.
  3. The CA publishes the updated CRL at the CDP URL.
  4. A client downloads the CRL and checks whether the serial number appears.

That model is simple and still widely supported. It is also the part that becomes painful at scale.

What CRLs do well

CRLs have a few practical strengths:

  • easy to understand
  • easy to mirror and cache
  • work in offline-ish environments if pre-fetched
  • signed by the CA, so tampering is detectable
  • useful in internal PKI where you control clients and update schedules

In private PKI, I still see CRLs used successfully, especially for VPN, smart card, and client certificate environments where endpoints are domain-managed and predictable.

The CRL size problem

The weakness is that a CRL is a list, and lists grow.

A busy public CA can revoke a large number of certificates. That means the CRL file can become large enough to hurt connection setup or cause stale-cache behavior. I have seen environments where revocation checks were theoretically enabled but practically useless because endpoints were using outdated CRLs or timing out while trying to fetch them.

With CRLs, the client downloads the whole list even though it only needs to know the status of one certificate. That design was acceptable in older, more centralized environments. On the public internet, it is inefficient.

You can inspect a CRL file locally like this:

openssl crl -in exampleca.crl -inform DER -noout -text

Or for PEM:

openssl crl -in exampleca.crl -inform PEM -noout -text

When troubleshooting, I usually check three things first:

  • Last Update
  • Next Update
  • whether the target serial number is present

Common CRL mistakes

These are the mistakes I see most often:

  • publishing the CRL URL internally where external clients cannot reach it
  • letting the CRL expire without regeneration
  • rotating CA infrastructure but forgetting old CDP URLs still appear in issued certificates
  • serving the CRL over a flaky endpoint with poor caching behavior

Validation is easy:

curl -I http://crl.exampleca.com/exampleca.crl
curl -O http://crl.exampleca.com/exampleca.crl
openssl crl -in exampleca.crl -inform DER -noout -text

If the URL is dead or the Next Update time has passed, you already have a revocation reliability problem.

OCSP: asking about one certificate at a time

Online Certificate Status Protocol was introduced to solve the “download the entire list” problem.

Instead of fetching a big CRL, the client sends a status request for one certificate to the CA’s OCSP responder. The response typically says one of three things:

  • good
  • revoked
  • unknown

This is far more efficient than CRLs for public web traffic. It also introduces a new issue: now the CA can learn which sites clients are connecting to.

Non-stapled OCSP

In the older, direct model:

  1. the browser receives the server certificate
  2. it reads the OCSP responder URL from AIA
  3. it contacts the responder itself
  4. it asks for the status of that certificate

That works, but it adds latency and leaks metadata. The CA, or whoever operates the responder, can observe a stream of certificate status lookups that correlates with browsing behavior.

This is one reason privacy-minded operators have never loved classic OCSP.

OCSP stapling

OCSP stapling improves that design.

The server periodically fetches a signed OCSP response from the CA and “staples” it to the TLS handshake. The browser can then validate revocation status without making its own direct request to the CA.

Benefits:

  • lower client latency
  • reduced load on the CA responder
  • better privacy than direct OCSP lookups
  • fewer outbound client dependencies

If I have a public HTTPS site under my control, I prefer stapling whenever the CA supports it.

There is a more detailed configuration article here: OCSP stapling in Nginx.

How OCSP stapling looks in Nginx

A typical Nginx configuration includes:

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/ca-chain.pem;
resolver 1.1.1.1 1.0.0.1 valid=300s ipv6=off;
resolver_timeout 5s;

A few practical notes from experience:

  • ssl_trusted_certificate should include the issuer chain used to verify the OCSP response.
  • If DNS resolution on the server is broken, stapling breaks quietly or half-works.
  • After enabling stapling, always reload and test from outside the box.

Reload Nginx safely:

sudo nginx -t && sudo systemctl reload nginx

Check whether a stapled response is being served:

echo | openssl s_client -connect example.com:443 -servername example.com -status

Look for output similar to:

OCSP response:
======================================
OCSP Response Status: successful
Cert Status: good

If you see no response sent, the configuration or upstream CA support needs work.

Apache OCSP stapling basics

Apache configuration is different but the goal is the same:

SSLUseStapling On
SSLStaplingCache shmcb:/var/run/ocsp(128000)
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors Off

Then validate and reload:

sudo apachectl configtest
sudo systemctl reload apache2

Or on RHEL-like systems:

sudo httpd -t
sudo systemctl reload httpd

I have seen Apache stapling fail because the cache path did not exist, SELinux blocked access, or the issuer chain was incomplete. Those are still worth checking before you blame the CA.

OCSP Must-Staple: useful, but not magic

Some certificates include the TLS Feature extension commonly called OCSP Must-Staple. The intent is clear: a compliant client should require a stapled OCSP response and treat the connection as invalid if the staple is missing.

That sounds attractive, especially if you dislike browser soft-fail behavior. But it raises the operational stakes. If your server stops stapling due to DNS problems, CA responder outages, broken chain files, or misconfiguration, clients that honor Must-Staple can fail hard.

You can inspect the extension with:

openssl x509 -in server.crt -noout -text | grep -A3 "TLS Feature"

I only recommend Must-Staple when you understand your deployment pipeline well enough to test stapling continuously. Otherwise you risk self-inflicted outages.

Browser behavior when OCSP is unreachable: the soft-fail problem

This is the part many people find frustrating.

If a browser cannot reach the OCSP responder, or the response is missing, or the network blocks the check, many browsers soft-fail. That means they continue the connection instead of rejecting the certificate.

Why? Because hard-failing on every revocation lookup problem would make the web fragile. CA outages, captive portals, enterprise filtering, and broken middleboxes would cause a lot of legitimate sites to fail.

From an operator’s perspective, soft-fail weakens revocation. A revoked certificate may not be rejected immediately by every client in every condition.

That is why I treat revocation as one control among several:

  • short lifetimes
  • prompt certificate replacement
  • CT log monitoring
  • key protection
  • stapling where possible

If you are not already watching CT logs, this pairs well with certificate transparency logs and why they matter.

Chrome CRLSet and similar browser-side mechanisms

Chrome historically used CRLSet, a compact browser-maintained blocklist for a subset of revoked certificates. The key phrase is “subset.” CRLSet was never a complete replacement for the web PKI revocation system.

It was mostly aimed at high-impact revocations such as major CA incidents and high-profile misissuance. That means:

  • it can protect users from some dangerous revoked certs
  • it does not contain every revoked certificate
  • you should not assume your routine revocation will be enforced by CRLSet

Browsers have evolved their own approaches over time, but the big practical point remains: browser-side revocation assistance is selective and not comprehensive.

What happens when a certificate is revoked in practice

When a certificate is revoked, several things are supposed to happen:

  1. the CA records the revocation reason and timestamp
  2. the certificate serial appears in the CRL and/or yields revoked via OCSP
  3. clients that perform and honor revocation checks reject the certificate
  4. administrators deploy a replacement certificate

In real operations, the effects depend on client type.

Browsers

Browsers may reject immediately if they have a strong revocation signal, especially with a stapled revoked response or major browser-managed blocklist coverage. They may also continue under soft-fail conditions if the revocation path is unavailable.

API clients and command-line tools

Some tools do very little revocation checking by default. Others can be configured to do more. I have seen teams assume that “TLS validation” automatically included reliable revocation checking in every client library. It often does not.

Enterprise endpoints

Managed desktops, VPN clients, and middleware can enforce CRL or OCSP much more strictly than consumer browsers. In those environments, revocation may be more meaningful because you control both ends of the policy.

How to check revocation status with OpenSSL

The quickest place to start is the live TLS connection.

Check for OCSP stapling:

echo | openssl s_client -connect example.com:443 -servername example.com -status

To extract the certificate and inspect issuer details:

echo | openssl s_client -connect example.com:443 -servername example.com -showcerts 2>/dev/null

If you already have the leaf and issuer certificates, you can query an OCSP responder directly:

openssl ocsp \
  -issuer issuer.pem \
  -cert server.pem \
  -url http://ocsp.exampleca.com \
  -resp_text \
  -noverify

A direct response may show:

server.pem: good
        This Update: Jul 22 11:00:00 2026 GMT
        Next Update: Jul 29 11:00:00 2026 GMT

Or, for a revoked certificate:

server.pem: revoked
        Revocation Time: Jul 20 08:14:37 2026 GMT

For CRL-based checks, download the CRL and inspect it:

curl -O http://crl.exampleca.com/exampleca.crl
openssl crl -in exampleca.crl -inform DER -noout -text

Then compare the serial number from the certificate:

openssl x509 -in server.pem -noout -serial

Troubleshooting revocation problems

When revocation status is not behaving the way you expect, I work through a short list.

1. Confirm the certificate actually changed

I have seen “revocation problems” that were really deployment problems. The edge node was still presenting the old certificate.

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -serial -issuer -dates

2. Check AIA and CDP URLs

Make sure the certificate points to reachable endpoints.

openssl x509 -in server.pem -noout -text | grep -A5 "Authority Information Access"
openssl x509 -in server.pem -noout -text | grep -A5 "CRL Distribution Points"

3. Validate the responder or CRL endpoint from the server and from outside

curl -I http://ocsp.exampleca.com
curl -I http://crl.exampleca.com/exampleca.crl

Outbound filtering on the server is a common reason stapling fails.

4. Test stapling specifically

echo | openssl s_client -connect example.com:443 -servername example.com -status

If the response is absent, check resolver configuration, issuer chain files, and server logs.

5. Distinguish revoked from unreachable

A responder timeout is not the same as a revoked answer. Logically obvious, but easy to blur during incident response.

Security considerations and current best practice

A few practical conclusions have held up well for me:

Short-lived certificates help more than people expect

Ninety-day certificates are not a nuisance in a well-automated environment. They are risk reduction. If a key compromise occurs and revocation checking is inconsistent, a short lifetime limits the blast radius.

Stapling is worth enabling

For public web servers, stapling improves privacy and efficiency. It is not complicated once you understand the trust chain and DNS dependencies.

Do not rely on revocation as your only defense

Revocation is necessary, but it has known limits:

  • soft-fail client behavior
  • client inconsistency
  • privacy trade-offs in direct OCSP
  • stale CRLs
  • server misconfiguration breaking stapling

Monitor what the public internet sees

After certificate replacement or revocation, validate externally. Do not stop at local file inspection. Tools like openssl s_client tell you what the service is really presenting. I use them constantly, and in complex cases I also compare with OpenSSL chain verification techniques and an s_client-focused debugging workflow.

Deprecated ideas and current reality

A few assumptions are outdated and worth saying plainly.

Deprecated assumption: revocation always protects users quickly

Not reliably. It can, but not universally.

Deprecated practice: treating CRLs alone as enough for public web PKI

For internet-facing services, CRLs alone are usually too blunt and too heavy. OCSP and stapling are more practical, though still imperfect.

Current reality: layered controls matter more

What works today is a combination of:

  • short certificate validity
  • automation for renewals and replacement
  • revocation support through OCSP and stapling
  • CT monitoring
  • disciplined key handling

Conclusion

Certificate revocation exists because certificates sometimes become unsafe before they expire. CRLs were the original answer, and they still make sense in controlled environments. OCSP improved efficiency, but introduced privacy and reliability trade-offs. Stapling made OCSP better for web servers, yet browser soft-fail behavior still limits how forcefully revocation is enforced on the public internet.

That is the real-world takeaway I use: enable revocation mechanisms, especially OCSP stapling, but do not overestimate them. Keep certificate lifetimes short, protect private keys, monitor issuance, and always verify from the outside after an incident. Revocation matters. It just does not work like a perfect kill switch.

Scroll to Top