SSL certificate expires within 30 days
What is this issue?
The site's SSL/TLS certificate is valid today, but it runs out within the next 30 days and has not been replaced yet.
Nothing is broken at the moment. Browsers still trust the certificate, the padlock still shows, and visitors notice nothing. The problem is the date: when it passes, every browser stops loading the site and shows a full-page security warning instead.
For a page to pass this check:
- The certificate it is served with has more than 30 days of validity left.
Short-lived certificates are judged by their own lifetime. Some certificate authorities now issue certificates that last 45 days, or even 6 days, and renew them automatically long before they expire. Such a certificate spends most or all of its life inside "30 days", so for these the window is one third of the certificate's lifetime instead — the point at which automatic renewal is normally due. For the common 90-day and one-year certificates the window is exactly 30 days.
An already expired certificate is a different finding. Once the date has passed (or before the start date has arrived), the page is reported as "SSL certificate expired" instead. The two are never reported together.
Why it matters
An expired certificate takes the whole site offline. Chrome, Safari, Firefox and Edge all replace the page with a full-screen "Your connection is not private" warning. Most visitors leave; many cannot get past it at all.
Search engines see the same failure. Crawlers that hit a certificate error cannot fetch the page. A long outage means pages drop out of results, and rankings can take time to recover after the fix.
Thirty days is the normal renewal point. Automated clients such as certbot renew a 90-day certificate when 30 days remain. A certificate still inside that window usually means renewal failed silently — a broken cron job, an expired DNS credential, a load balancer that never picked up the new file.
It is cheap to fix now and expensive to fix later. Today it is a routine renewal. After expiry it is an incident, often discovered by customers.
Effect on the health score
This is an important issue. It deducts from the Delivery & Trust score for each affected page until the certificate is renewed.
How to fix it
Renew the certificate now. With Let's Encrypt and certbot:
sudo certbot renew sudo systemctl reload nginx # or apache2, haproxy, ...With a commercial certificate authority, request a new certificate, install it, and reload the server.
Make sure the server actually uses the new file. A renewed certificate on disk does nothing until the web server, load balancer or CDN reloads it. Check what is being served:
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -datesFind out why automatic renewal did not run. Check the renewal timer or cron job (
systemctl list-timers | grep certbot), its logs, DNS API credentials used for DNS-01 challenges, and that port 80 is reachable for HTTP-01 challenges.Check every place the certificate lives. CDNs, load balancers, and separate servers for
wwwand the bare domain each hold their own copy.Add monitoring. An alert at 21 days remaining catches the next failure before this check does.
Examples
Example 1: A one-year certificate with 12 days left
Valid from: 2025-10-12
Valid until: 2026-10-13
Scan date: 2026-10-01Reported: 12 days remain, which is inside the 30-day window.
Example 2: A 90-day certificate that renewed on time
Valid from: 2026-09-20
Valid until: 2026-12-19
Scan date: 2026-10-01Passes: 79 days remain.
Example 3: A 6-day certificate in the middle of its life
Valid from: 2026-09-28
Valid until: 2026-10-04
Scan date: 2026-10-01Passes: 3 days remain, but the certificate only lasts 6 days. Its window is one third of its lifetime (2 days), and it is not there yet. Reporting it would flag a site whose automated renewal is working perfectly.
Example 4: A certificate that has already expired
Valid until: 2026-09-29
Scan date: 2026-10-01Not this issue: it is reported as "SSL certificate expired" instead.
How PixyScan detects this
Only HTTPS pages are checked. A page served over plain HTTP has no certificate; that is reported separately as "Page not served over HTTPS".
Reads the certificate the server presents with a TLS handshake to the page's host. The result is cached per host for the scan, so a 10,000-page site costs one handshake, not 10,000.
Says nothing if the certificate could not be read. A timeout or refused connection is not evidence about the certificate, so no finding is raised.
Leaves expired and not-yet-valid certificates to the expiry check. Only a certificate that is valid right now can be "expiring soon".
Measures the time left from now until the certificate's "valid until" date, and the certificate's total lifetime from its "valid from" date.
Reports when the time left is at most 30 days, or at most one third of the lifetime if that is shorter. A 398-day or 90-day certificate is reported at 30 days; a 45-day certificate at 15; a 6-day certificate at 2.
Records the whole days remaining (rounded down), the expiry date and the issuer on the finding.
What we store
Storage Level
Page Level
Database Table / Prisma Model
PageSecurityHeader, and the finding on audit_issues.details
Fields Used
| Field | Type | Description |
|---|---|---|
| page_security_headers.ssl_certificate_issuer | String | Who issued the certificate |
| page_security_headers.ssl_valid_from | DateTime | Start of the validity window, used for the certificate's lifetime |
| page_security_headers.ssl_valid_until | DateTime | End of the validity window |
Stored Fields on the finding
| Field | Type | Description |
|---|---|---|
| message | String | The days remaining and the expiry date |
| sslCertificateIssuer | String | The issuer |
| sslValidFrom | DateTime | Start of the validity window |
| sslValidUntil | DateTime | End of the validity window |
| daysRemaining | Int | Whole days left at scan time, rounded down |
Detection Dependencies
- TLS handshake with the page's host (cached per host for the scan)