ArticlesSSL

Incomplete certificate chains, explained

Your certificate is signed by an intermediate, which is signed by a root. If the server leaves out the intermediate, most browsers cope and some apps fail. What that means and how to fix it.

A certificate is trusted because of who signed it. Your server has to send your certificate together with the intermediate that signed it. When the intermediate is missing, most browsers still open the site, and some apps, scripts and devices refuse to connect.

What an intermediate is

A certificate authority keeps its root certificate offline and signs day to day with an intermediate certificate. So the chain has three links:

  1. Root: already built into every browser and operating system. Your server doesn't send it.
  2. Intermediate: signed by the root. Your server must send it.
  3. Your certificate: signed by the intermediate, for your host name.

A visitor's device can only link your certificate to a root it trusts if it has the intermediate in between. An incomplete chain means the server sends your certificate on its own.

Why most browsers cope

Browsers fill the gap. Many remember intermediates they've seen on other sites, and some fetch a missing intermediate from the address written inside your certificate. So the site looks fine when you open it yourself, and the problem goes unnoticed.

Which clients fail

Clients that don't fill the gap stop with an error. That includes:

  • command-line tools like curl: unable to get local issuer certificate;
  • scripts and apps in many programming languages, for example Java's PKIX path building failed;
  • payment providers, shipping services and other partners that call your webhooks or your API;
  • some older phones and devices.

So an incomplete chain often shows up as a message from one partner whose integration stopped working, while the site opens fine in every browser you try.

How to fix it

Install the full chain your certificate provider gives you: your certificate first, then the intermediate. The root isn't needed.

  • Certbot (Let's Encrypt): use fullchain.pem, not cert.pem.
  • nginx: ssl_certificate points at the full chain file.
  • Apache 2.4.8 and later: SSLCertificateFile points at the full chain file.
  • Hosting panel: paste the intermediate into the field called "CA bundle", "chain" or "intermediate".
  • Load balancer or CDN: upload the chain along with the certificate.
nginxserver block
ssl_certificate     /etc/letsencrypt/live/yourshop.dk/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourshop.dk/privkey.pem;

Reload the web server, then look at the result with the free chain inspector.

When the intermediate changesCertificate authorities switch intermediates from time to time. A chain pasted in by hand stays the old one, so a renewal can break a chain that worked for years. Using the full chain file from each renewal avoids that.

Keeping an eye on it

SSL Monitor checks the chain every day over a real TLS handshake, along with the expiry and the TLS settings. An incomplete chain shows up even while your own browser opens the site without a warning.

Related

All SSL articles · SSL blog

No surprise expiries

Expiry, issuer and chain. Free, with no sign-up.Daily monitoring for a business: SSL Pro, €18 a month for 20 hosts. Personal site? Monitor it free.