curl and its CA bundle
Two curls on one machine can trust two different lists, depending on the TLS library each was built with.
Which list curl reads
curl trusts the CA bundle it was built or told to use: a file such as /etc/ssl/certs/ca-certificates.crt, given with --cacert or CURL_CA_BUNDLE. A curl built on Schannel, the Windows TLS library - like the curl.exe in C:\Windows\System32 - reads the Windows store instead, and ignores CURL_CA_BUNDLE (curl manual).
So the curl in System32, the one inside Git for Windows and one from a package manager can each give a different answer for the same URL.
See which store each curl reads
certdoctor https://the-url-that-fails/
The trust matrix has a row for every curl it finds. certdoctor asks each one how it was built, with curl --version, and judges it by the list that build reads. A curl on Schannel points at the Windows store’s row rather than repeating it:
curl C:\Windows\system32\curl.exe does NOT trust the presented chain (90 anchors) - it judges
by system-store CurrentUser, which refuses it detected
Its fix is that store’s command. A curl reading a bundle gets an append to that bundle.
Add the root
- A curl on Schannel: add the root to the Windows store - the Windows certificate store.
- A curl reading a bundle: append the root to the bundle, as the row prints it. On Linux that bundle is usually the distribution’s - the Linux CA bundle.
What not to do
curl -k and --insecure skip verification for that request. They are fine for looking at a broken server on purpose, and wrong as a fix.