Ignoring SSL Certificate Issues with cURL

Ignoring SSL Certificate Issues with cURL

When making a request with cURL to a secured (HTTPS) endpoint, cURL will automatically verify the authenticity and validity of the certificate during the handshake before sending the request. There are times when you might want to bypass this check and tell cURL to make the request anyways; for example, on a development server with a self-signed certificate.

The Short Answer

You can bypass the certificate verification by adding the [.inline-code]-k[.inline-code] or [.inline-code]--insecure[.inline-code] flag to your request.

 $ curl https://expired.badssl.com/
curl: (60) SSL certificate problem: certificate has expired

$ curl https://expired.badssl.com/ -k
<!DOCTYPE html>

[#easily-recall-this-command-with-ai]Easily recall this command with AI[#easily-recall-this-command-with-ai]

If you are using Warp, you can get to this request using the AI Command Search by typing [.inline-code]#[.inline-code] and then [.inline-code]curl ignore ssl[.inline-code]

 # curl ignore ssl

[#bypassing-an-insecure-proxy]Bypassing an insecure proxy with cURL [#bypassing-an-insecure-proxy]

There are situations where you are making a cURL request through a proxy server and the problematic certificate is not from the final endpoint you are requesting, but it is rather a problem with the intermediate proxy-server’s certificate.

In situations like this, you can use the [.inline-code]--proxy-insecure[.inline-code] flag together with the [.inline-code]-k[.inline-code] /  [.inline-code]--insecure[.inline-code] flag above to bypass the security checks.

For example, if you start a local HTTPs proxy with something like [.inline-code]mitmproxy[.inline-code]:

 $ mitmproxy

It should open a local proxy server, and you can then see that trying to make a request through it, even to a legitimate endpoint, will give an error:

 $ curl https://google.com --proxy https://localhost:8080
curl: (60) SSL certificate problem: unable to get local issuer certificate

By adding the two flags, we can get the request to go through:

 $ curl https://google.com --proxy https://localhost:8080 --proxy-insecure -k
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<H1>301 Moved</H1>
The document has moved
<A HREF="https://www.google.com/">here</A>.

[#disabling-verification-system-wide] Disabling certificate verification system-wide[#disabling-verification-system-wide]

There are some situations where you may want to disable this certificate verification system-wide. For example, if the [.inline-code]curl[.inline-code] requests in question are being generated by some script (Python, PHP, etc.) and it would be a lot of effort to update all the locations making requests.

In situations like these, if you need an easy way to temporarily disable SSL verification system-wide, you can add [.inline-code]insecure[.inline-code] and optionally [.inline-code]proxy-insecure[.inline-code] to your [.inline-code]~/.curlrc[.inline-code] file.


Adding them to your [.inline-code]~/.curlrc[.inline-code] will have exactly the same effect as passing them as command line options, so you can use whichever option better fits your situation. 

[#potential-security-concerns] Beware of potential security concerns [#potential-security-concerns]

When you bypass cURL’s verification of the TLS / SSL certificate, TLS / SSL becomes less able to secure your connection. This leaves you exposed to risks like man-in-the-middle attacks, where, for example, a malicious actor can gain access to your traffic and impersonate the server you are trying to reach by returning its own certificate instead of the real one. This would allow the malicious actor to decrypt your requests.

So this workaround should only be used in situations where you know why the certificate is invalid and you temporarily want to make the request despite the associated risks. Some typical examples of this situation could be:

  • Sending a request to a development server that has a self-signed certificate
  • Your certificate just recently expired and you want to make the cURL request before getting it renewed

A more robust solution for situations like the above, where you want to work with a self-signed certificate, would be to make cURL trust your personal root certificate authority’s (CA) certificate, and leave verification on. This would allow you to still make the request, but have the protection against issues like the attack discussed above.

To do this, you will need the root CA certificate which signed your server’s certificate. In the [.inline-code]mitmproxy[.inline-code] example from above, you can get the certificate using:

 $ curl http://mitm.it/cert/pem --proxy https://localhost:8080 -k --proxy-insecure > cacert.pem

You can then use that certificate in other cURL requests as follows:

 $ curl https://google.com --proxy https://localhost:8080 --proxy-cacert ./cacert.pem --cacert ./cacert.pem

To read more about retrieving and using root CA certificates you can take a look at this post by Daniel Stenberg, one of the maintainers of cURL.