Safeguard
Developer Tools•

Why does my certificate work in a browser but fail in curl or Java?

A certificate that works in one client and fails in another often means a missing intermediate. Spot an incomplete chain and fix it with fullchain.pem.

Safeguard Security Team
3 min read

The usual cause is an incomplete certificate chain: your server sends the leaf certificate but not the intermediate that links it to a trusted root. Some clients can work around that gap and others cannot. The fix is to serve the full chain, for example fullchain.pem from Certbot.

What a chain is

A TLS server proves its identity with a certificate signed by an intermediate certificate authority, which is signed by a root that clients already trust. The client must be able to build the path from your certificate to a root it holds. If the server does not send the intermediate, the client has to find it elsewhere, and not every client will.

TLS 1.3 sets the rules for what the server sends. The end-entity certificate must come first, and each following certificate should certify the one before it. A certificate that is a trust anchor may be left out when peers are known to have it. Intermediates are not in that category for the public web, so send them.

How to spot it

Run a handshake and count what the server sends:

openssl s_client -connect example.com:443 -servername example.com -showcerts

Look at the certificate list. If you see one certificate where you expect two, the intermediate is missing. Also read the verify return code at the end. A message about being unable to get local issuer certificate is the classic sign.

Another check is to compare clients. A desktop browser might succeed while a command line client, a Java service or a mobile library fails. A difference between clients on the same host points to the chain, not the leaf.

Fix it

  1. Identify the file your server uses for its certificate.
  2. Replace it with the file that contains the leaf first, followed by the intermediates.
  3. With Certbot, fullchain.pem holds all certificates, with the server certificate first and intermediates after it. Nginx expects that file for ssl_certificate, and Apache 2.4.8 and later does for SSLCertificateFile. The smaller cert.pem and chain.pem files are separate pieces, for software that wants them split.
  4. Reload the server and repeat the openssl check.

Other causes to rule out

  • Wrong order. Leaf first, then each issuer.
  • Extra certificates. Servers sometimes send an old and a new intermediate during a transition. TLS 1.3 tells implementations to tolerate that, but trim it if you can.
  • Hostname mismatch, which is a different failure. See hostnames and the SAN field.
  • Expired intermediate on your side or a stale trust store on the client.

Do not fix a chain problem by turning verification off. See what to do instead of disabling TLS verification.

Where Safeguard fits

Safeguard scans dependencies and SBOMs for known vulnerabilities, including those in the TLS and crypto libraries your projects pull in, and you can try it with the free scan at gold.safeguard.sh/scan.

Quick check

Do I need to send the root certificate?

Usually not. Clients hold their trust anchors, so send the leaf and the intermediates.

Which Certbot file should my web server use?

fullchain.pem for the certificate and privkey.pem for the key.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.