SSL error with requests 2.28.x: certificate verify failed: unable to get local issuer certificate

<!-- Summary. -->

While doing an HTTP post transfer of report payloads with requests version 2.28.1 and SSL verification set to True, the request fails giving error (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1091)')))
However when I downgrade the requests module to 2.27.1 it works successfully

The client ssl certificate was installed on the windows cert store. Question is why does the request on version 2.27 succeeds and why does it complain when the version is 2.28.1? Has something changed the way requests picks up the SSL certificates from the windows store?

## Expected Result

Successful transfer of reports with SSL verification set to True in version 2.28.x

## Actual Result

(Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1091)')))

## System Information

    $ python -m requests.help

```json
{
  "chardet": {
    "version": null
  },
  "charset_normalizer": {
    "version": "2.0.12"
  },
  "cryptography": {
    "version": ""
  },
  "idna": {
    "version": "3.3"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.9.10"
  },
  "platform": {
    "release": "10",
    "system": "Windows"
  },
  "pyOpenSSL": {
    "openssl_version": "",
    "version": null
  },
  "requests": {
    "version": "2.28.1"
  },
  "system_ssl": {
    "version": "101010df"
  },
  "urllib3": {
    "version": "1.26.12"
  },
  "using_charset_normalizer": true,
  "using_pyopenssl": false
}
```

<!-- This command is only available on Requests v2.16.4 and greater. Otherwise,
please provide some basic information about your system (Python version,
operating system, &c). -->


The main change is that disabling certificate checking by setting an environment variable to an empty value is no longer valid in 2.28. Requests has never used the windows cert store. It's likely you were unwittingly ignoring verification before by having an env var set to globally disable certificate checking 

@sigmavirus24 I did not set any env variables, so if I do not set any env variable did it mean that it considered it as an empty string and disabled certificate verification from windows cert store? Also what is the env var that we talking about here? Is it "CURL_CA_BUNDLE" ? Which I see in the requests changelogs? Was it by default set to empty string?
What is the resolution to this other than explicitly mentioning the cert path during request? I did come across `pip-system-certs` or  `python-certifi-win32` https://stackoverflow.com/questions/50422136/python-requests-with-wincertstore

> so if I do not set any env variable did it mean that it considered it as an empty string and disabled certificate verification from windows cert store?

No that's not what it means. You would have had to set either environment variable explicitly and then forgotten.

At no point in time has requests ever relied on the windows cert store and the package your referencing monkey patches this library in a way that is incompatible with advanced usage of the library and I would not recommend it

@sigmavirus24 Got it. What would be the recommended way to do it? Would it be by explicitly specifying the path to certificate while making the request? Like
```
import requests
r = requests.get('https://server/api', auth=(user,password), verify='/path/to/cert.pem')
```
Or is there another way you would recommend to do this?

Sorry I think you edited to add a second library `pip-system-certs` monkey patches in an incompatible way.

I have no experience with the wincertstore library.

Windows didn't store files which is why requests doesn't work with it without some other library.

One way might be too use the second library. Another night be to expert the site's certificate chain to a pem encoded file as you suggest. That's documented in other issues and better documented by OpenSSL itself.

I encourage you to check if either variable CURL_CA_BUNDLE or REQUESTS_CA_BUNDLE are set empty in your environment. The reason we broke that is because people can set it and forget it and that's exactly why it's dangerous. 

Got it. Thanks for the suggestions @sigmavirus24