Your WordPress plugins won't update, a payment gateway webhook keeps failing, or a REST API call to another service just times out with a cryptic message in the error log: cURL error 60: SSL certificate problem: unable to get local issuer certificate. Nothing changed on your end, and the site itself loads fine in the browser — so what's actually broken?
Symptom: Where This Error Shows Up
This isn't a visitor-facing SSL warning. Your site's own certificate can be perfectly valid while this error still happens, because it's about outbound connections your server makes to other servers, not inbound connections from browsers to you. You'll typically spot it in:
- WordPress admin, when checking for plugin/theme updates — the update screen just shows a blank list or an error instead of available updates.
- PHP error logs, as a fatal or warning line referencing
cURL error 60orSSL certificate problem: unable to get local issuer certificate. - WooCommerce or any payment gateway plugin (Razorpay, Stripe, PayPal) failing to reach the gateway's API — orders get stuck or webhooks silently fail.
- License-check calls for premium plugins/themes (Elementor Pro, ACF Pro, etc.) failing, so the plugin nags about an invalid license even though it's active.
- Any custom code using
wp_remote_get(),wp_remote_post(), or raw cURL to talk to an external API. - The command line, if you test with
curlover SSH:curl: (60) SSL certificate problem: unable to get local issuer certificate, followed by curl's own explanation that it "failed to verify the legitimacy of the server and therefore could not establish a secure connection to it." Same error, same cause — the wording just comes from the curl tool instead of PHP.
Cause: An Outdated or Missing CA Bundle
When your server makes an outbound HTTPS request, cURL has to verify the remote server's certificate against a list of trusted Certificate Authorities — the CA bundle (usually cacert.pem or the system's ca-certificates package). If that bundle is old, corrupted, or missing entirely, cURL can't complete the chain of trust and refuses to connect. Three things usually cause this:
- The OS-level CA bundle is stale. Certificate Authorities rotate their intermediate and root certs periodically. A server that hasn't run system updates in a year or two is missing newer roots, so requests to sites using those newer chains fail.
- PHP's
curl.cainfopoints to the wrong place (or nowhere). On shared hosting with multiple PHP versions, it's common for one version'sphp.inito have a validcurl.cainfopath and another to have none at all, or a path to a file that no longer exists after a server migration. - The remote endpoint changed its certificate chain. Less common, but if an API provider switched CAs (Let's Encrypt's chain changes over the years are a classic example), an old bundle that used to work suddenly doesn't.
You can confirm it's the CA bundle and not a one-off network blip by testing from SSH:
curl -v https://api.wordpress.org/plugins/update-check/1.1/ 2>&1 | grep -i "certificate\|SSL"If you see unable to get local issuer certificate in that output, it's confirmed — this is a local trust-store problem, not an issue with the remote server.
Fix: Shared cPanel Hosting
On shared hosting you don't have root, so you're working within what cPanel and WHM expose:
- Open MultiPHP INI Editor in cPanel and check the
curl.cainfodirective for the PHP version your site actually runs (Site Health in WordPress tells you the exact version if you're not sure). If it's blank, that's often fine — most modern PHP builds bundle their own trusted roots via OpenSSL and don't need it set explicitly. If it points to a path, verify that file exists. - Ask your host to update the server's
ca-certificatespackage. This is the real fix in most cases, and on shared hosting it has to happen at the server level, not per-account. A quick support ticket referencing "outdated CA bundle causing cURL error 60" is usually enough for a competent host to resolve it same-day. (If you're on Getwebup, our support team runs this as routine maintenance, but flag it if you're still seeing the error after a plugin update.) - As a temporary diagnostic only, some guides suggest downloading a fresh
cacert.pemfrom curl.se and pointingcurl.cainfoat it in your account'sphp.inioverride. This works, but it's a workaround, not a fix — that file goes stale again in a year, and now you have to remember to refresh it. Push for the server-level update instead.
Fix: VPS / Root Access
If you manage the server yourself, this is a two-minute fix:
| OS | Command |
|---|---|
| Ubuntu / Debian | sudo apt-get update && sudo apt-get install --reinstall ca-certificates && sudo update-ca-certificates |
| AlmaLinux / CentOS / RHEL | sudo yum update ca-certificates (or dnf on newer releases) |
After updating, restart PHP-FPM (or Apache/LiteSpeed if you're not on FPM) so the new trust store is picked up by running PHP processes:
sudo systemctl restart php-fpm
sudo systemctl restart httpd # or nginx / lsws, depending on your stackRe-run the curl -v test from earlier. If it's clean, check WordPress plugin updates again — they should populate normally now.
What Not to Do
You'll find plenty of old forum posts suggesting you add this to wp-config.php or a plugin's HTTP request filter:
add_filter( 'https_ssl_verify', '__return_false' );Don't. This disables certificate verification entirely for outbound WordPress requests, which means your site can no longer tell the difference between the real update server and an attacker sitting in the middle of the connection (a classic man-in-the-middle setup). It makes the symptom disappear without fixing the actual trust-store problem — and it quietly weakens every other outbound HTTPS call your site makes, including payment gateway traffic. Fix the CA bundle instead; it's not meaningfully harder and it's the difference between "fixed" and "hidden."
Prevention
- Keep the server's OS packages current. Most distros patch
ca-certificatesautomatically with routine security updates — if your VPS hasn't had an update in months, this is one of several reasons to fix that. - If you maintain a custom
cacert.pemfor any reason, set a recurring reminder (or a cron job) to refresh it from curl.se rather than letting it age silently. - On multi-PHP-version servers, check
curl.cainfoconsistency across versions after any PHP upgrade or server migration — it's an easy setting to lose track of. - Monitor for this specific error string in your PHP error log; catching it once, quietly, beats discovering it when a customer's payment silently fails to confirm.