<p dir="auto">When <code class="notranslate">REQUESTS_CA_BUNDLE</code> is defined, the CA certificate passed to <code class="notranslate">requests.Session</code> constructor is overridden when <code class="notranslate">requests.Session.request</code> is called.</p>
<p dir="auto">Guilty method/lines:<br>
<a href="https://github.com/psf/requests/blob/master/requests/sessions.py#L694-L710">https://github.com/psf/requests/blob/master/requests/sessions.py#L694-L710</a></p>
<h2 dir="auto">Expected Result</h2>
<p dir="auto">I would expect for the priority to be:</p>
<ol dir="auto">
<li><code class="notranslate">requests.Session.request</code> verify kwarg</li>
<li><code class="notranslate">requests.Session</code> verify property</li>
<li><code class="notranslate">REQUESTS_CA_BUNDLE</code> / <code class="notranslate">CURL_CA_BUNDLE</code></li>
</ol>
<h2 dir="auto">Actual Result</h2>
<p dir="auto">As <code class="notranslate">requests.Session.request</code> verify kwarg was not set, it took the value from <code class="notranslate">REQUESTS_CA_BUNDLE</code> and only then <code class="notranslate">requests.Session.verify</code> was checked, but ignored, resulting in an invalid CA used (for that Session).</p>
<p dir="auto">Related issue (in docker-py project) <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="497257247" data-permission-text="Title is private" data-url="https://github.com/docker/docker-py/issues/2433" data-hovercard-type="issue" data-hovercard-url="/docker/docker-py/issues/2433/hovercard" href="https://github.com/docker/docker-py/issues/2433">docker/docker-py#2433</a></p>
<h2 dir="auto">System Information</h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$ python -m requests.help"><pre class="notranslate"><code class="notranslate">$ python -m requests.help
</code></pre></div>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="{
  &quot;chardet&quot;: {
    &quot;version&quot;: &quot;3.0.4&quot;
  },
  &quot;cryptography&quot;: {
    &quot;version&quot;: &quot;2.7&quot;
  },
  &quot;idna&quot;: {
    &quot;version&quot;: &quot;2.8&quot;
  },
  &quot;implementation&quot;: {
    &quot;name&quot;: &quot;CPython&quot;,
    &quot;version&quot;: &quot;3.7.4&quot;
  },
  &quot;platform&quot;: {
    &quot;release&quot;: &quot;18.6.0&quot;,
    &quot;system&quot;: &quot;Darwin&quot;
  },
  &quot;pyOpenSSL&quot;: {
    &quot;openssl_version&quot;: &quot;1010103f&quot;,
    &quot;version&quot;: &quot;19.0.0&quot;
  },
  &quot;requests&quot;: {
    &quot;version&quot;: &quot;2.22.0&quot;
  },
  &quot;system_ssl&quot;: {
    &quot;version&quot;: &quot;1000213f&quot;
  },
  &quot;urllib3&quot;: {
    &quot;version&quot;: &quot;1.25.3&quot;
  },
  &quot;using_pyopenssl&quot;: true
}"><pre class="notranslate"><code class="notranslate">{
  "chardet": {
    "version": "3.0.4"
  },
  "cryptography": {
    "version": "2.7"
  },
  "idna": {
    "version": "2.8"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.7.4"
  },
  "platform": {
    "release": "18.6.0",
    "system": "Darwin"
  },
  "pyOpenSSL": {
    "openssl_version": "1010103f",
    "version": "19.0.0"
  },
  "requests": {
    "version": "2.22.0"
  },
  "system_ssl": {
    "version": "1000213f"
  },
  "urllib3": {
    "version": "1.25.3"
  },
  "using_pyopenssl": true
}
</code></pre></div>
<p dir="auto">One would expect that when the caller explicitly asks to make unverified requests, then the <code class="notranslate">REQUESTS_CA_BUNDLE</code> environment variable doesn't affect it. The reality is different, however.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import os
import requests

os.environ['REQUESTS_CA_BUNDLE'] = 'asd.pem'  # Must be an existing file

r = requests.get('https://self-signed.badssl.com/', verify=False)
print(r)
# Prints: &lt;Response [200]&gt;

session = requests.Session()
session.verify = False

r = session.get('https://self-signed.badssl.com/')
print(r)
# Fails: requests.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">os</span>
<span class="pl-k">import</span> <span class="pl-s1">requests</span>

<span class="pl-s1">os</span>.<span class="pl-s1">environ</span>[<span class="pl-s">'REQUESTS_CA_BUNDLE'</span>] <span class="pl-c1">=</span> <span class="pl-s">'asd.pem'</span>  <span class="pl-c"># Must be an existing file</span>

<span class="pl-s1">r</span> <span class="pl-c1">=</span> <span class="pl-s1">requests</span>.<span class="pl-en">get</span>(<span class="pl-s">'https://self-signed.badssl.com/'</span>, <span class="pl-s1">verify</span><span class="pl-c1">=</span><span class="pl-c1">False</span>)
<span class="pl-en">print</span>(<span class="pl-s1">r</span>)
<span class="pl-c"># Prints: &lt;Response [200]&gt;</span>

<span class="pl-s1">session</span> <span class="pl-c1">=</span> <span class="pl-s1">requests</span>.<span class="pl-v">Session</span>()
<span class="pl-s1">session</span>.<span class="pl-s1">verify</span> <span class="pl-c1">=</span> <span class="pl-c1">False</span>

<span class="pl-s1">r</span> <span class="pl-c1">=</span> <span class="pl-s1">session</span>.<span class="pl-en">get</span>(<span class="pl-s">'https://self-signed.badssl.com/'</span>)
<span class="pl-en">print</span>(<span class="pl-s1">r</span>)
<span class="pl-c"># Fails: requests.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)</span></pre></div>