[GH-ISSUE #165] WordPress health check error: curl: (60) SSL certificate problem: unable to get local issuer certificate #105

Closed
opened 2026-02-25 22:32:36 +03:00 by kerem · 16 comments
Owner

Originally created by @emmtre on GitHub (May 26, 2019).
Original GitHub issue: https://github.com/FiloSottile/mkcert/issues/165

It this a known issue with macOS Mojave (10.14.5)? I have problems with site health check in WordPress 5.2.1 and REST API and loopback requests.

curl https://local.website.com
curl: (60) SSL certificate problem: unable to get local issuer certificate
Originally created by @emmtre on GitHub (May 26, 2019). Original GitHub issue: https://github.com/FiloSottile/mkcert/issues/165 It this a known issue with macOS Mojave (10.14.5)? I have problems with site health check in WordPress 5.2.1 and REST API and loopback requests. ``` curl https://local.website.com curl: (60) SSL certificate problem: unable to get local issuer certificate ```
kerem closed this issue 2026-02-25 22:32:36 +03:00
Author
Owner

@emmtre commented on GitHub (May 26, 2019):

curl -v https://local.website.com

* Rebuilt URL to: https://local.website.com/
* Trying ::1...
* Connected to local.website.com (::1) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* Successfully set certificate verify locations:
* CAfile: /share/curl/curl-ca-bundle.crt
* CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS alert, Server hello (2):
* SSL certificate problem: unable to get local issuer certificate
* Closing connection 0

curl: (60) SSL certificate problem: unable to get local issuer certificate
<!-- gh-comment-id:496016870 --> @emmtre commented on GitHub (May 26, 2019): ``` curl -v https://local.website.com * Rebuilt URL to: https://local.website.com/ * Trying ::1... * Connected to local.website.com (::1) port 443 (#0) * ALPN, offering http/1.1 * Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH * Successfully set certificate verify locations: * CAfile: /share/curl/curl-ca-bundle.crt * CApath: none * TLSv1.2 (OUT), TLS header, Certificate Status (22): * TLSv1.2 (OUT), TLS handshake, Client hello (1): * TLSv1.2 (IN), TLS handshake, Server hello (2): * TLSv1.2 (IN), TLS handshake, Certificate (11): * TLSv1.2 (OUT), TLS alert, Server hello (2): * SSL certificate problem: unable to get local issuer certificate * Closing connection 0 curl: (60) SSL certificate problem: unable to get local issuer certificate ```
Author
Owner

@Cobs commented on GitHub (May 31, 2019):

I got the same message with Debian.
Fixed it by manualy adding the mkcert's CA Certificate into the local CA cert store and set the extention from .pem to .crt

<!-- gh-comment-id:497795603 --> @Cobs commented on GitHub (May 31, 2019): I got the same message with Debian. Fixed it by manualy adding the mkcert's CA Certificate into the local CA cert store and set the extention from .pem to .crt
Author
Owner

@emmtre commented on GitHub (May 31, 2019):

The CA Certificate is added to the macOS system store automatically. When using /usr/bin/curl everything is working as expected. But WordPress is using it's own version of curl so the installed mkcert's CA Certificate is not found. I have also tried to set curl.cainfo without success. Any other ideas?

curl.cainfo=/Users/Username/Library/Application\ Support/mkcert/rootCA.pem

<!-- gh-comment-id:497827964 --> @emmtre commented on GitHub (May 31, 2019): The CA Certificate is added to the macOS system store automatically. When using `/usr/bin/curl` everything is working as expected. But WordPress is using it's own version of `curl` so the installed mkcert's CA Certificate is not found. I have also tried to set `curl.cainfo` without success. Any other ideas? `curl.cainfo=/Users/Username/Library/Application\ Support/mkcert/rootCA.pem`
Author
Owner

@healdev commented on GitHub (May 31, 2019):

Same problem here...
Running WordPress 5.2.1 on local OS X Mojave
curl command works with no issue in terminal but WordPress HealthCheck throws a curl error 60... for REST API and Loopback requests.

Anybody solved that?

ps: @emmtre not sure but shouldn't the path be wrapped in double quotes for the curl.cainfo setting?

<!-- gh-comment-id:497886838 --> @healdev commented on GitHub (May 31, 2019): Same problem here... Running WordPress 5.2.1 on local OS X Mojave curl command works with no issue in terminal but WordPress HealthCheck throws a curl error 60... for REST API and Loopback requests. Anybody solved that? ps: @emmtre not sure but shouldn't the path be wrapped in double quotes for the curl.cainfo setting?
Author
Owner

@healdev commented on GitHub (May 31, 2019):

The only hack I could find on my local dev environment is to manually edit /wp-includes/certificates/ca-bundle.crt and append the content of /Users/Username/Library/Application\ Support/mkcert/rootCA.pem to end of file
That solved the problem, I just need to find a long-term solution...maybe a must-use plugin that would check and edit the file automatically... or I'll try to find a hook

<!-- gh-comment-id:497888519 --> @healdev commented on GitHub (May 31, 2019): The only hack I could find on my local dev environment is to manually edit /wp-includes/certificates/ca-bundle.crt and append the content of /Users/Username/Library/Application\ Support/mkcert/rootCA.pem to end of file That solved the problem, I just need to find a long-term solution...maybe a must-use plugin that would check and edit the file automatically... or I'll try to find a hook
Author
Owner

@healdev commented on GitHub (May 31, 2019):

Ok so there is a filter to deal with this issue.
Since I have this issue only on my local dev env, I created a must-use plugin that checks if the environment is local and looks for certificate in the desired file.

if ( '127.0.0.1' === $_SERVER['REMOTE_ADDR'] ) {
	add_filter( 'http_request_args', function( $r, $url ) {
		$r['sslcertificates'] = '/<ABS-PATH-TO-YOUR-PEM>/cacert.pem';
		return $r;
	}, 10, 2);
}
<!-- gh-comment-id:497891965 --> @healdev commented on GitHub (May 31, 2019): Ok so there is a filter to deal with this issue. Since I have this issue only on my local dev env, I created a must-use plugin that checks if the environment is local and looks for certificate in the desired file. ``` if ( '127.0.0.1' === $_SERVER['REMOTE_ADDR'] ) { add_filter( 'http_request_args', function( $r, $url ) { $r['sslcertificates'] = '/<ABS-PATH-TO-YOUR-PEM>/cacert.pem'; return $r; }, 10, 2); } ```
Author
Owner

@FiloSottile commented on GitHub (Jun 1, 2019):

Yeah, WordPress is configuring curl to use a hardcoded CA list, so there's not much mkcert can do.

* Successfully set certificate verify locations:
* CAfile: /share/curl/curl-ca-bundle.crt

Closing this as it's not a mkcert issue, but thanks for providing a workaround, and maybe consider opening an issue with WordPress to use the system store, I don't think there's any good reason not to.

<!-- gh-comment-id:497941358 --> @FiloSottile commented on GitHub (Jun 1, 2019): Yeah, WordPress is configuring curl to use a hardcoded CA list, so there's not much mkcert can do. ``` * Successfully set certificate verify locations: * CAfile: /share/curl/curl-ca-bundle.crt ``` Closing this as it's not a mkcert issue, but thanks for providing a workaround, and maybe consider opening an issue with WordPress to use the system store, I don't think there's any good reason not to.
Author
Owner

@simongcc commented on GitHub (Feb 25, 2020):

@healdev I am meeting the same situation. And found that there is a filter for updating the path. I have created a certificate for local use and point to that by calling the filter and put it inside functions.php.

add_filter( 'http_request_args', 'modify_ca_cert_location', 10, 2 );
function modify_ca_cert_location( $r ) {
$r['sslcertificates'] = WP_CONTENT_DIR.'/themes/wp-theme-name/ssl/ca-bundle.crt';
return $r;
}

<!-- gh-comment-id:590763727 --> @simongcc commented on GitHub (Feb 25, 2020): @healdev ~~I am meeting the same situation. And found that there is a filter for updating the~~ path. ~~I have created a certificate for local use and point to that by calling the filter and put it inside `functions.php`.~~ ~~add_filter( 'http_request_args', 'modify_ca_cert_location', 10, 2 ); function modify_ca_cert_location( $r ) { $r['sslcertificates'] = WP_CONTENT_DIR.'/themes/wp-theme-name/ssl/ca-bundle.crt'; return $r; }~~
Author
Owner

@simongcc commented on GitHub (Mar 1, 2020):

@healdev
Ops, I think I have overlooked and missed your solutions by just scanning through without reading in depth.
Sorry about that.

<!-- gh-comment-id:593108661 --> @simongcc commented on GitHub (Mar 1, 2020): @healdev Ops, I think I have overlooked and missed your solutions by just scanning through without reading in depth. Sorry about that.
Author
Owner

@Kevinlearynet commented on GitHub (Apr 19, 2020):

This isn't an issue with mkcert, like @FiloSottile mentioned, it's ultimately something caused by the way WordPress handles cURL requests. Here's the specific line causing it:

github.com/WordPress/WordPress@856e1a27b8/wp-includes/class-http.php (L209)

I've fixed this myself in a Homebrew installed PHP 7.4 localhost using this function:

/**
 * Replace Localhost cURL Certificates
 *
 * If the URL for an HTTP request in WordPress contains a .test
 * TLD, replace the WordPress local /certificates/ca-bundle.crt
 * with the PHP supplied bundle.
 */
function curl_patch_http_request_args( $parsed_args, $url ) {

	// Request URL points to a *.test host
	$test_tld = end( explode( ".", parse_url( $url, PHP_URL_HOST ) ) );
	if ( ! $test_tld ) return $parsed_args;

	// Replace WordPress local certificates with PHP's default cacert path
	$openssl_cert_locations = openssl_get_cert_locations();
	if ( isset( $openssl_cert_locations['default_cert_file'] ) ) {
		$parsed_args['sslcertificates'] = $openssl_cert_locations['default_cert_file'];
	}

	return $parsed_args;
}
add_filter( 'http_request_args', 'curl_patch_http_request_args', 99, 2 );

This will filter all HTTP class instances, replacing the locally used cURL certificate authority at /wp-includes/certificates/ca-bundle.crt with the certificate authority currently used by PHP for any request to a *.test TLD. I use .test domains locally, but if you use other URL's be sure to adjust this part.

<!-- gh-comment-id:616002942 --> @Kevinlearynet commented on GitHub (Apr 19, 2020): This isn't an issue with `mkcert`, like @FiloSottile mentioned, it's ultimately something caused by the way WordPress handles cURL requests. Here's the specific line causing it: https://github.com/WordPress/WordPress/blob/856e1a27b8dfa9208c36b8b474afcb5acc90322b/wp-includes/class-http.php#L209 I've fixed this myself in a Homebrew installed PHP 7.4 localhost using this function: ``` /** * Replace Localhost cURL Certificates * * If the URL for an HTTP request in WordPress contains a .test * TLD, replace the WordPress local /certificates/ca-bundle.crt * with the PHP supplied bundle. */ function curl_patch_http_request_args( $parsed_args, $url ) { // Request URL points to a *.test host $test_tld = end( explode( ".", parse_url( $url, PHP_URL_HOST ) ) ); if ( ! $test_tld ) return $parsed_args; // Replace WordPress local certificates with PHP's default cacert path $openssl_cert_locations = openssl_get_cert_locations(); if ( isset( $openssl_cert_locations['default_cert_file'] ) ) { $parsed_args['sslcertificates'] = $openssl_cert_locations['default_cert_file']; } return $parsed_args; } add_filter( 'http_request_args', 'curl_patch_http_request_args', 99, 2 ); ``` This will filter all HTTP class instances, replacing the locally used cURL certificate authority at `/wp-includes/certificates/ca-bundle.crt` with the certificate authority currently used by PHP for any request to a *.test TLD. I use .test domains locally, but if you use other URL's be sure to adjust this part.
Author
Owner

@netnaps commented on GitHub (Jun 24, 2020):

i had the same issue it was just because of another plugin named really simple ssl , deactivated the same and it worked.

<!-- gh-comment-id:648859713 --> @netnaps commented on GitHub (Jun 24, 2020): i had the same issue it was just because of another plugin named really simple ssl , deactivated the same and it worked.
Author
Owner

@petertwise commented on GitHub (Sep 23, 2020):

Thanks for the great research on this issue everyone. I made some of the solutions presented here into a dropin plugin:
https://github.com/squarecandy/force-localhost-ca

<!-- gh-comment-id:697081197 --> @petertwise commented on GitHub (Sep 23, 2020): Thanks for the great research on this issue everyone. I made some of the solutions presented here into a dropin plugin: https://github.com/squarecandy/force-localhost-ca
Author
Owner

@nylen commented on GitHub (Oct 16, 2020):

maybe consider opening an issue with WordPress to use the system store, I don't think there's any good reason not to

For what it's worth, there are very good reasons not to use the system cert store. One of them is that WordPress and ClassicPress run on a very wide variety of servers, which includes servers that unfortunately have not been updated in a long time. This would cause many legitimate requests to fail.

<!-- gh-comment-id:710442659 --> @nylen commented on GitHub (Oct 16, 2020): > maybe consider opening an issue with WordPress to use the system store, I don't think there's any good reason not to For what it's worth, there are very good reasons not to use the system cert store. One of them is that WordPress and ClassicPress run on a very wide variety of servers, which includes servers that unfortunately have not been updated in a long time. This would cause many legitimate requests to fail.
Author
Owner

@Werverton commented on GitHub (Dec 16, 2021):

I got the same message with Debian. Fixed it by manualy adding the mkcert's CA Certificate into the local CA cert store and set the extention from .pem to .crt

In which local?

<!-- gh-comment-id:995950492 --> @Werverton commented on GitHub (Dec 16, 2021): > I got the same message with Debian. Fixed it by manualy adding the mkcert's CA Certificate into the local CA cert store and set the extention from .pem to .crt In which local?
Author
Owner

@Cobs commented on GitHub (Dec 19, 2021):

I got the same message with Debian. Fixed it by manualy adding the mkcert's CA Certificate into the local CA cert store and set the extention from .pem to .crt

In which local?

I'm not sure i understand the question.
As told in the update-ca-certificate program's manual, I just copied the mkcert certificate in /usr/local/share/ca-certificates as a .crt file then ran update-ca-certificate

<!-- gh-comment-id:997455097 --> @Cobs commented on GitHub (Dec 19, 2021): > > I got the same message with Debian. Fixed it by manualy adding the mkcert's CA Certificate into the local CA cert store and set the extention from .pem to .crt > > In which local? I'm not sure i understand the question. As told in the [update-ca-certificate program's manual](https://www.unix.com/man-page/linux/8/update-ca-certificates/), I just copied the mkcert certificate in /usr/local/share/ca-certificates as a .crt file then ran update-ca-certificate
Author
Owner

@Werverton commented on GitHub (Dec 20, 2021):

In my case, I solved the problem inserting the SSLCACertificate /Path/to/domain.ca-bundle in virtual host .conf . The cURL needs the Chain of certificate.

<!-- gh-comment-id:997583604 --> @Werverton commented on GitHub (Dec 20, 2021): In my case, I solved the problem inserting the SSLCACertificate /Path/to/domain.ca-bundle in virtual host .conf . The cURL needs the Chain of certificate.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/mkcert#105
No description provided.