sfw/fix
SEC_ERROR_EXPIRED_CERTIFICATE critical

SEC_ERROR_EXPIRED_CERTIFICATE (Firefox)

Firefox blocks the site because the certificate's validity end date has passed, or the local clock is wrong enough to make a valid cert look expired.

What you see

Warning: Potential Security Risk Ahead

example.com uses an invalid security certificate. The certificate expired on <date>.

Error code: SEC_ERROR_EXPIRED_CERTIFICATE

What’s actually happening

Firefox throws "Potential Security Risk Ahead" and names the expiry date. Two very different situations look identical. If the cert truly lapsed, every visitor hits it at once and traffic stops. If only your machine's clock is wrong, you see it and nobody else does. Firefox runs its own date check independent of Chrome, so cross-checking another browser doesn't always disambiguate — read the date in the error instead.

Common causes

  • The cert passed its notAfter date — auto-renewal failed or was never set up
  • A Let's Encrypt renewal timer (certbot.timer / systemd-timer) quietly stopped running weeks ago
  • The cert renewed on disk but the web server was never reloaded, so Firefox is still served the old expired file
  • The local system clock is wrong (dead CMOS battery, bad timezone, NTP not syncing), pushing "now" past a valid cert's window
  • A long-lived intermediate in the chain expired, even though the leaf is still valid

How to fix it

  1. Read the dates and decide: server or clockecho | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates prints the real notBefore/notAfter. If they're valid, check your own clock — a wrong device date triggers this with nothing wrong server-side. If notAfter has genuinely passed, it's the cert.
  2. Fix the clock if that's the causeWrong local time makes a fine cert look expired. macOS/Linux: enable automatic time (timedatectl set-ntp true, or System Settings > Date & Time). Windows: Settings > Time & language > Sync now. A drained motherboard battery resets the clock on every reboot — replace it. Reload Firefox after.
  3. Renew the certificateLet's Encrypt: certbot renew (add --force-renewal if it claims it isn't due yet). Paid cert: reissue through the provider and install the new files. Confirm the new notAfter is roughly 90 days out (LE) or a year (paid).
  4. Reload the web server so the new cert goes liveA renewed cert on disk isn't served until the server reloads it — "renewed but still expired" is a classic trap. systemctl reload nginx (or apache2), then re-run the openssl -dates check to confirm the fresh dates are actually being served.
  5. Repair renewal so it can't recursystemctl status certbot.timer to confirm the auto-renew job is active and ran recently. Most expired-cert outages are a renewal task that died silently — re-enable it and add a deploy/post-renew hook that reloads the server on each renewal.

Stop it recurring

Run an external SSL monitor that alerts 14+ days before notAfter, and pair auto-renewal with a post-renew reload hook so a renewed cert actually gets served.

Related errors