Defaults.Exposed

Not secure: the five things that put that label on your site

Chrome writes “Not secure” beside your address when it couldn’t build a connection it trusts to the page it’s showing you. Five different faults produce those same two words: the site answers only on plain HTTP, the certificate has expired, the certificate doesn’t cover the name the visitor typed, nobody trusts the certificate at all, or the page sits on valid HTTPS and loads one thing over http://. That last one is why people who’ve already installed a certificate end up here, and it’s the one most guides leave out. Working out which of the five you have takes a couple of minutes, and none of the fixes cost money.

Two warnings that look alike and aren’t

The inline label is the milder of the two: the page renders normally, and “Not secure” sits in the address bar where the padlock would be. Chrome shows it on any page served over plain HTTP, and on an HTTPS page that pulled in something over HTTP.

The other is the full-page interstitial. The page doesn’t render at all; the visitor gets a grey screen, “Your connection is not private”, and an error code such as NET::ERR_CERT_DATE_INVALID, NET::ERR_CERT_COMMON_NAME_INVALID or NET::ERR_CERT_AUTHORITY_INVALID. That screen means the browser tried HTTPS and the certificate failed validation. The error code names the cause for you, which is why the triage below starts by reading it.

The difference matters commercially. With the inline label, the visitor sees your page and a small warning. With the interstitial, the warning renders before your page does, and most visitors take the “Back to safety” button.

Find out which of the five you have

Load the page in Chrome and look at what you’ve got.

If the address starts with http:// and there’s no padlock, you have cause one. Nothing about certificates applies yet.

If you’re looking at the interstitial, read the code: DATE_INVALID points at cause two, COMMON_NAME_INVALID at cause three and AUTHORITY_INVALID at cause four. Click “Advanced” and the text below the code repeats the same diagnosis in words.

If the address starts with https://, the page renders, and the label still says “Not secure”, you have cause five. Press F12, open the Console tab, reload, and look for a line that begins “Mixed Content: The page at ‘https://…’ was loaded over HTTPS, but requested an insecure image ‘http://…’”. Each line names the exact asset that did it.

For causes two to four, the command line tells you more than the browser does. Run this against your own hostname:

openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -dates -subject -issuer -ext subjectAltName

The output gives you the validity window, who issued the certificate, and each hostname it covers. Compare the dates with today, and compare the subjectAltName list with the address your visitor typed, www and all.

Cause one: the site only answers on HTTP

Plain HTTP is the simplest case, and still a common one. Of the 316,600,902 domains where the September 2026 census ran its HTTPS check, 104,446,408 (33.0%) answered on HTTP only. Those sites carry the inline label on each page they serve, and since they don’t have a certificate yet there’s nothing to repair, only something to set up.

Turning HTTPS on is a configuration task. Let’s Encrypt issues certificates free, and most hosts and CDNs will request and renew one for you when you flick a switch in their panel. On a server you run yourself, certbot or your web server’s ACME client does the same in a few commands.

After that, and this is where people stop short, HTTP has to redirect to HTTPS with a 301, or the http:// address keeps working and keeps carrying the label. The HSTS header then tells browsers to go straight to HTTPS on the next visit, so the first plaintext request doesn’t happen at all.

A site that has lived on HTTP for years is full of http:// image and script paths that were harmless while the page was HTTP too. The moment the page moves to HTTPS, those paths become cause five. Reload with the console open after the switch.

Cause two: the certificate expired

Certificates are short-lived by design, and the modern ones are issued for 90 days or less. That’s fine when renewal is automated, which is how nearly all of them are meant to work. So when a visitor sees NET::ERR_CERT_DATE_INVALID, the usual story is a renewal job that stopped running a while ago and a certificate that has since run down its clock.

The openssl command above shows the notAfter date. If it’s in the past, find out why renewal stopped. The usual reasons are a cron job or systemd timer that was lost in a server migration, port 80 closed by a firewall change so the HTTP-01 challenge can’t be answered, an expired API token for the DNS-01 challenge, or a hosting panel where the auto-renew box was never ticked.

Renewal can also run and still leave the old certificate in place: the new one lands on disk, and the web server keeps serving the old one from memory because nothing reloaded it. A certbot renew dry run will pass in that case while the site still shows the interstitial. Check the certificate the server is presenting, with openssl, rather than the file on disk.

Across the 212,154,494 domains the census could reach over HTTPS, 23,036,743 (10.9%) presented a certificate that failed validation. Expired certificates are part of that group, and they get there without anyone changing anything on the server, which is what makes the fault easy to miss. Once the renewal is running again and the server has reloaded, look at the label once more; if it’s still there with the page rendering, you’ve moved on to cause five.

Cause three: the certificate doesn’t cover that hostname

A certificate lists the names it’s valid for in the subjectAltName field. If a visitor types www.example.com and the certificate only lists example.com, or the other way round, Chrome shows NET::ERR_CERT_COMMON_NAME_INVALID. Nothing is wrong with the certificate itself in that case; it was issued for a name the visitor didn’t type.

It’s easy to miss because you test the address you always use and your visitors use the other one. Search results, old links and the habit of typing www all send traffic to whichever name you didn’t check.

Reissue with both names. Let’s Encrypt and the hosts that use it will happily put the apex and www on the same certificate; most panels have a checkbox for it, and certbot -d example.com -d www.example.com does it on the command line. Redirecting www to the apex doesn’t get you out of it, because the redirect is sent over the HTTPS connection that the bad certificate already broke.

The same fault appears when a subdomain is pointed at a server whose certificate was issued for the main site only, or when a wildcard certificate is expected to cover the apex, which it doesn’t. Read the subjectAltName list and check each name your visitors reach.

Cause four: nobody trusts the certificate

NET::ERR_CERT_AUTHORITY_INVALID means the browser can’t trace the certificate back to an authority it trusts. Two configurations produce it.

The first is a self-signed certificate. It encrypts the connection, and no browser will ever trust it, because no authority vouched for it. These are fine for internal tooling and wrong for anything the public visits. Replace it with an issued certificate; the free one takes minutes.

The second is an incomplete chain. Your certificate was issued by an intermediate authority, which was issued by a root the browser trusts. The server has to send the intermediate along with your certificate. If it sends only yours, some clients fill the gap by fetching the intermediate themselves or by having it cached from another site, and others don’t. The same site can work on your laptop and fail on a phone, or in one browser and not another, and people lose days checking the wrong thing.

In the openssl output, “unable to get local issuer certificate” is the incomplete chain and “self signed certificate” is the self-signed case. The chain fix is usually one line: serve fullchain.pem rather than cert.pem, or paste the intermediate into the certificate field of your hosting panel. The TLS check in the scan tests the chain the way a client with an empty cache does, so it catches the case your own browser hides.

Cause five: a valid certificate and one http:// asset

People who search for why a site with SSL still shows the label have landed on this cause, and the certificate has nothing to do with it. The page came in over HTTPS with a valid certificate, and then it asked for an image, a stylesheet, a font, a script or an iframe over http://. Chrome calls this mixed content. For a passive asset such as an image, it loads the thing and downgrades the label to “Not secure”. For an active asset such as a script, it blocks the load, the page breaks in some way, and the console explains why.

The console line from the triage step names the offending asset. To find where it comes from, view the page source and search for src="http://, href="http:// and url(http://. In a content management system the usual culprits are a site URL setting that still says http://, image paths saved into the database when the site was HTTP, a theme that hard-codes a font or icon set, and a third-party embed that was pasted years ago.

Fix the paths at source where you can: change http:// to https:// on each one, and change the CMS site URL so new content is written correctly. Where there are thousands of old posts, a search-and-replace on the database does it in one pass.

The header Content-Security-Policy: upgrade-insecure-requests works as a server-side backstop: it tells the browser to rewrite any http:// request on the page to https:// before it’s sent. It clears the label in one line and it doesn’t fix the page, so use it alongside the path clean-up rather than instead of it, and check that each upgraded asset answers over HTTPS. The headers piece covers where that line goes on the common servers.

The census doesn’t measure mixed content, because it means fetching and parsing the page itself rather than checking the connection, so there’s no number to give you for how common it is. For your own page, the console count of mixed-content lines is the figure to work from.

Once the label has gone

Reload in a private window so a cached asset doesn’t flatter you, and reload on a phone, because the incomplete-chain case hides on the machine you fixed it from. Then confirm that http:// redirects to https:// with a 301 and that the HSTS header is being sent, since those two are what keep the label from coming back after the next content edit or server move.

Run the free scan on your domain and you get the certificate dates, the names it covers, the chain as a cold client sees it, the redirect and the HSTS header in one report, with the failing item named. Fix what it lists, then run it again to check the label has gone.

Figures as of 5 September 2026, from the September 2026 edition of the defaults.exposed census. Census numbers move every month; the current values are on the census data page.