How to fix curl error 60: SSL certificate problem: certificate has expired error

From September 30, 2021, WordPress websites that use Let’s Encrypt certificates are having issues with HTTP API requests.

For example, here is an example that will cause this error:

$res = wp_remote_get( 'https://abcdef.com/' );
if( is_wp_error( $res ) ){
	echo $res->get_error_message();
}

the error message:

cURL error 60: SSL certificate problem: certificate has expired

What causes this error?

WordPress core has a root certificate file /wp-includes/certificates/ca-bundle.crt that is used to check SSL for all requests created via HTTP API. In this file, one of the root certificates used to create the certificate for your site has expired. Therefore, the request fails verification and generates this error.

Detailed explanation from the Let’s Encrypt team:

Without going into details, for non-professionals, a few words about why the expired  DST Root CA X3certificate will affect the certificate issued by Let’s Encrypt. Every system that verifies certificates has its own repository of trusted root certificates. The system will trust certificates signed with the private key of one of these root certificates during verification. The root certificate itself usually has a long expiration date, is rarely changed and is not used when generating the final subject certificate (domain name certificate in this case). On the contrary, the public key infrastructure means the use of a chain of trust – the root certificate is used To sign the intermediate certificates and have used them to sign the final subject certificate (domain certificate). In addition, in order for the system to trust the final subject certificate, it must be able to trace the complete chain from that certificate to one of the root certificates it trusts.

When Let’s Encrypt appeared, its ISRG Root X1root certificate (just like any new root certificate) could not quickly enter the trusted certificate store of a large number of systems. At the same time, in order for the project to run successfully, the certificates issued from the beginning must be trusted by the largest number of “out-of-the-box” systems (the users of these systems do not have any additional actions). In this regard, for certificates, Let’s Encrypt began to use the chain of trust leading to the root certificate DST Root CA X3, which is recognized by most systems.

https://docs.certifytheweb.com/docs/kb/kb-202109-letsencrypt/

This issue is resolved in WordPress 5.9, but if you are using some older WP version and don’t plan to update WordPress but need a valid HTTP request, here is a quick workaround:

CURL error 60: SSL certificate has expired solution

So far I’ve tested only two solutions and here are they:

A: Manually

Step 1. Download the following file: https://curl.se/ca/cacert.pem

Step 2. From your FTP/FileManager navigate to the /wp-includes/certificates folder

Step 3. Replace the content of the ca-bundle.crt file with the downloaded file from step 1

B: Code Snippet

Step 1. Add the following code snippet inside your theme functions.php file

/**
 * Goto http://yoursite.com/?update-wp-ca-bundle
 */

if( isset( $_GET['update-wp-ca-bundle'] ) ){

	$crt_file = ABSPATH . WPINC . '/certificates/ca-bundle.crt';
	$new_crt_url = 'http://curl.haxx.se/ca/cacert.pem';

	if( is_writable( $crt_file ) ){
		$new_str = file_get_contents( $new_crt_url );

		if( $new_str && strpos( $new_str, 'Bundle of CA Root Certificates' ) ){
			$up = file_put_contents( $crt_file, $new_str );

			echo $up ? 'OK: ca-bundle.crt updated' : 'ERROR: can`t put data to ca-bundle.crt';
		}
		else {
			echo 'ERROR: can\'t download curl.haxx.se/ca/cacert.pem';
		}
	}
	else {
		echo 'ERROR: ca-bundle.crt not writable';
	}

	exit;
}

Step 2. Visit http://yoursite.com/?update-wp-ca-bundle

Step 3. Remove the snippet from your functions.php file

Was this post helpful?

Leave a Comment