Views: 21

curl: (60) SSL certificate problem — fix

curl: (60) SSL certificate problem means curl can't trust the chain. Check the intermediate, your CA bundle, and any proxy. Free instant check, no sign-up.

Check your domain for this issue now

Free, no sign-up. Runs the exact check this guide describes and shows what to fix.

Problem

curl stops with curl: (60) SSL certificate problem: unable to get local issuer certificate and refuses to continue. Exit code 60 is CURLE_PEER_FAILED_VERIFICATION — curl received a certificate but could not build a trusted chain from it back to a certificate authority it recognizes. The certificate itself is usually fine. What’s missing is a link: either the server didn’t send the intermediate that connects its certificate to a public root, or your machine doesn’t hold the root (or intermediate) needed to complete the chain, or something between you and the server swapped the certificate for one signed by a CA you don’t trust. The whole job is figuring out which of those three it is.

Symptoms

  • The full message is curl: (60) SSL certificate problem: unable to get local issuer certificate. The trailing text is OpenSSL’s verify result num=20 (X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY).
  • Close relatives point at different chain problems: self signed certificate in certificate chain (verify error 19) means a private/interception CA is in the path; self signed certificate (18) means the endpoint presented its own root; unable to verify the first certificate (21) means the server sent a leaf with no intermediate at all.
  • If it fails for one host but others work: the problem is that host’s chain — almost always a missing intermediate on the server.
  • If it fails for every HTTPS host: the problem follows you, not the site — a missing/stale CA bundle or local TLS interception.

Top 3 Causes

  1. The server isn’t sending its intermediate certificate - The single most common cause for one specific host. The server presents only the leaf and leaves out the intermediate that chains it to a trusted root. Browsers often hide this by fetching the missing intermediate on their own; curl doesn’t, so it can’t complete the chain and stops at error 60. The fix is on the server — deploy the full chain (leaf + intermediate), not the leaf alone.
  2. Your CA bundle is missing, outdated, or wrong - When curl can’t find or read the trust store it was built to use, it has nothing to verify against and every HTTPS request fails. This is classic in minimal container images and freshly provisioned servers that never installed a ca-certificates package, or where curl was compiled to look for a bundle at a path that doesn’t exist. It also bites when a root has been rotated and an ancient bundle predates the new one.
  3. A proxy or antivirus is intercepting TLS - Corporate middleboxes and “HTTPS scanning” antivirus decrypt your traffic and re-sign it with their own private CA. That CA is trusted on managed machines but absent from a default curl bundle, so curl sees a certificate signed by an issuer it can’t find and reports error 60 — often as self signed certificate in certificate chain (19). On an unmanaged machine, the same signature is what a real attacker would produce, which is exactly why curl refuses it.

Diagnose with DechoNet

  • SSL Check shows the exact chain the server sends over the wire — whether the intermediate is present or the server is shipping the leaf alone. If the chain is incomplete here, you’ve confirmed cause #1 and the fix is on the server. If the chain looks complete from the public internet but curl still fails on your machine, the problem is local: your CA bundle or a proxy re-signing your traffic (cause #2 or #3).
  • HTTP Check confirms the endpoint actually responds once the certificate question is set aside, so you don’t chase a trust error on a host that’s also down.

Resolution Checklist

  • Read the scope first. One host failing while others work → server chain problem. Every host failing → your bundle or a local proxy. This one question routes the entire fix.
  • For one host, look at the served chain: curl -v https://YOUR_DOMAIN (watch the certificate lines) or openssl s_client -connect YOUR_DOMAIN:443 -servername YOUR_DOMAIN -showcerts. If you see only one CERTIFICATE block, the intermediate is missing — reinstall the certificate as a fullchain bundle. Re-run SSL Check to confirm the intermediate now appears.
  • For a bundle problem, install or refresh trusted roots: apt-get install --reinstall ca-certificates / update-ca-certificates (Debian, Ubuntu), or yum reinstall ca-certificates / update-ca-trust (RHEL, Fedora). Confirm the file curl expects actually exists (/etc/ssl/certs/ca-certificates.crt on Debian, /etc/pki/tls/certs/ca-bundle.crt on RHEL).
  • To point curl at a known-good bundle explicitly, use curl --cacert /path/to/ca-bundle.crt https://YOUR_DOMAIN, or download the current Mozilla bundle from https://curl.se/ca/cacert.pem. This is the correct fix, unlike -k, because verification stays on.
  • For a corporate proxy you’re supposed to trust, add its root to the bundle: append the proxy CA’s PEM to /etc/ssl/certs/ca-certificates.crt (or the platform equivalent) so curl can verify the re-signed certificate. If you don’t recognize the intercepting CA, stop — treat it as suspicious rather than trusting it blindly.
  • Resist curl -k. It disables the exact check that’s protecting you. If you use it at all, use it once to confirm the endpoint works, then remove it and fix the trust properly.

When to Escalate

  • If SSL Check shows a complete, correct chain from the public internet but curl still fails only on one machine, the CA doing the re-signing is on that machine’s network — a proxy or antivirus. That’s an endpoint/IT question (which root to trust and how to distribute it), not a per-request flag.
  • If the endpoint genuinely uses a private or self-signed CA (internal service, appliance, dev environment), the right move is to trust that specific CA via --cacert or the system store — not to turn verification off. Clicking past trust errors, or scripting around them with -k, trains you to ignore the one signal that separates your real server from an impostor.

Related Tools

Related Guides

Share this guide

[Ad] Guide Detail Inline
← Back to All Guides