Demystifying SSL Certificate Chains for Developers
Cover photo by Scott Rodgerson on Unsplash
const https = require('https');https.get('https://example.com', (res) => { // What happens if the server only sends the leaf cert?});What is wrong with that code? Nothing, provided your local environment has the complete trust store. That is the trap. You assume the server will do the heavy lifting, but it often does not. If your client environment lacks the intermediate CA certificate, your handshake fails with a generic error that sends you on a wild goose chase.
The chain explained
A certificate chain is just a list of trust. You have your server certificate, also known as the leaf. That leaf is signed by an intermediate certificate. That intermediate is signed by a root certificate. Browsers and OS vendors ship with a bundle of trusted root certificates. If your server sends the leaf but forgets the intermediate, the client has to fetch it from a URL defined in the Authority Information Access field of the certificate. This adds latency. Sometimes, it just breaks (I have spent way too long debugging this on embedded systems without a robust networking stack).
Why it breaks
You might say, “Wait, why do I care if the browser does this for me?” You are right, browsers are smart. They handle AIA fetching gracefully. But your backend service, your Python script, or your Go binary might not. If you are writing a microservice that calls another internal API, you are responsible for the trust chain. Do not rely on the client environment to fill in the blanks.
Trust is hierarchical
Think of it like a chain of custody. You trust the root, so you trust whoever the root signed, and so on. If you are configuring Nginx or Apache, make sure your full chain file includes the intermediate certificates. Just dumping the leaf certificate into your config is a classic developer pitfall.
I should mention that modern ACME clients like Certbot usually handle this for you. If you are using a manual process to upload certificates to a load balancer, that is where things get messy. I honestly prefer to automate everything because human error is the biggest security risk here.
Verification
You can always check the chain with OpenSSL:
openssl s_client -showcerts -connect example.com:443If the output only shows one certificate, your server is misconfigured. It should return the leaf and the intermediate chain. Does this matter for every single project? Probably not, but it matters the moment you need it to work reliably. Are you testing your certificate chain configuration in your staging environment before pushing to production? You should be.