ERTIFICATE security tls ai_generated true

SSL: CERTIFICATE_VERIFY_FAILED - unable to get local issuer certificate, even though cert is valid

ID: security/tls-certificate-chain-ordering

Also available as: JSON · Markdown
90%Fix Rate
92%Confidence
3Evidence
2023-01-01First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
any active

Root Cause

TLS requires the full certificate chain: leaf cert -> intermediate(s) -> root CA. Browsers often cache intermediates and work anyway, but programmatic clients (curl, Python requests, Node.js) fail. The server must send intermediates; the client only trusts root CAs.

generic

Workarounds

  1. 95% success Include full chain in order: leaf, intermediate(s), but NOT root
    cat server.crt intermediate.crt > fullchain.pem  # leaf first, then intermediate(s)
  2. 92% success Test with openssl s_client or SSL Labs, not just a browser
    openssl s_client -connect example.com:443 -showcerts  # verify full chain is sent
  3. 88% success Use ACME/certbot which automatically includes the correct chain
    certbot uses fullchain.pem by default which includes leaf + intermediates in correct order

Dead Ends

Common approaches that don't work:

  1. Install leaf certificate only, assuming clients have intermediate certs 92% fail

    Browsers cache intermediate certs from previous visits. curl, Python, and Node.js don't cache intermediates. They fail on every connection.

  2. Add root CA cert to the server's chain file 72% fail

    Root CA should NOT be in the chain. Clients already have root CAs in their trust store. Including it wastes bandwidth and can confuse some TLS implementations.

  3. Test TLS with a browser and assume all clients will work 88% fail

    Browsers have intermediate certificate caching (AIA fetching). Programmatic clients don't. Browser testing misses missing intermediate cert issues.