cpython icon indicating copy to clipboard operation
cpython copied to clipboard

SSL is broken on python 3.11 on M1 mac running Monterey

Open pragbatra-mendel opened this issue 3 years ago • 6 comments

Despite installing python 3.11 pkg from the python website and running the Install Certificates script which completes without error, I still get ssl certificate verify failed whenever I try to connect to a website that uses SSL. Running without verifying SSL certificates works fine. When I run openssl version I get LibreSSL 2.8.3, even though I installed openssl via homebrew. Is there any way to fix this?

pragbatra-mendel avatar Nov 03 '22 19:11 pragbatra-mendel

Are you sure that you are really using the python installed from the python.org website? It is very easy to be confused if you have more than one version of python installed; for instance, Apple provides a python3 with its Xcode / Command Line Tools. The easiest way to verify which you are using it to print the system version information along with a simple failing test; for the python.org 3.11.0 release, it should show v3.11.0:deaf509e8f, Oct 24 2022, 14:43:23. And other versions of OpenSSL, like provided by Homebrew, have no effect on the python.org-installed Python on macOS.

ned-deily avatar Nov 03 '22 20:11 ned-deily

Yes, I am using the official python installer and when I run python --version it shows 3.11.0. I did brew install openssl and brew link --force openssl and openssl version now shows OpenSSL 3.0.7 1 Nov 2022 (Library: OpenSSL 3.0.7 1 Nov 2022) instead of LibreSSL. When I try to download a file from an https site with urllib.request.urlopen().read().decode() it gives the below error:

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/urllib/request.py", line 1348, in do_open
    h.request(req.get_method(), req.selector, req.data, headers,
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/http/client.py", line 1282, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/http/client.py", line 1328, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/http/client.py", line 1277, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/http/client.py", line 1037, in _send_output
    self.send(msg)
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/http/client.py", line 975, in send
    self.connect()
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/http/client.py", line 1454, in connect
    self.sock = self._context.wrap_socket(self.sock,
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/ssl.py", line 517, in wrap_socket
    return self.sslsocket_class._create(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/ssl.py", line 1075, in _create
    self.do_handshake()
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/ssl.py", line 1346, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:992)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/urllib/request.py", line 216, in urlopen
    return opener.open(url, data, timeout)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/urllib/request.py", line 519, in open
    response = self._open(req, data)
               ^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/urllib/request.py", line 536, in _open
    result = self._call_chain(self.handle_open, protocol, protocol +
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/urllib/request.py", line 496, in _call_chain
    result = func(*args)
             ^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/urllib/request.py", line 1391, in https_open
    return self.do_open(http.client.HTTPSConnection, req,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/urllib/request.py", line 1351, in do_open
    raise URLError(err)
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:992)>

pragbatra-mendel avatar Nov 03 '22 21:11 pragbatra-mendel

Without more information, it is difficult to explain what you are reporting. If you are indeed using the python.org installation, it has its own embedded version of OpenSSL 1.1.1; it does not use or is affected at all by an OpenSSL installed via Homebrew or any other mechanism.

Please execute the following two commands in your terminal shell and paste the output here:

/Library/Frameworks/Python.framework/Versions/3.11/bin/python3.11 -c 'import sys;print(sys.version)'
/Library/Frameworks/Python.framework/Versions/3.11/bin/python3.11 -m pip list

Please also copy and paste the exact sequence of commands including the URL that gives the CERTIFICATE_VERIFY_FAILED error.

ned-deily avatar Nov 03 '22 22:11 ned-deily

/Library/Frameworks/Python.framework/Versions/3.11/bin/python3.11 -m pip list
3.11.0 (v3.11.0:deaf509e8f, Oct 24 2022, 14:43:23) [Clang 13.0.0 (clang-1300.0.29.30)]
Package            Version
------------------ ----------
certifi            2022.9.24
cffi               1.15.1
charset-normalizer 2.1.1
cryptography       38.0.3
idna               3.4
pip                22.3
pycparser          2.21
pyOpenSSL          22.1.0
requests           2.28.1
setuptools         65.5.0
urllib3            1.26.12

In my current environment, it looks like the error is specific to the URL of the file I'm trying to download. I'll check if it's reproducible on a working configuration on Intel architecture to see if the issue is specific to M1. Curl downloads the file fine so I suspect it is still an issue with python certificates however.

pragbatra-mendel avatar Nov 03 '22 22:11 pragbatra-mendel

Thanks for the response, that does look correct for the python.org 3.11.0 release. Whichever version of Curl you are using, it is undoubtedly using a somewhat different set of root certificates (i.e. it is not using those provided by the PyPI certifi package which is what is installed by Install Certificates.command so that might be an issue. You could try to check the certificate chain using OpenSSL and/or curl; see, for example, this.

ned-deily avatar Nov 03 '22 22:11 ned-deily

When I try to download a file from an https site with urllib.request.urlopen().read().decode() it gives the below error:

Does this happen with all websites or just some of them? Is one of the problematic websites a public website that you can share the name for (so that we can look at the certificate ourselves)?

ronaldoussoren avatar Nov 09 '22 16:11 ronaldoussoren

I propose closing this issue: The issue is likely in a particular website that has a certificate with a chain that's not rooted at a certificate trusted by the CA roots included with certifi. That's not something we can fix on our end.

ronaldoussoren avatar Nov 15 '22 10:11 ronaldoussoren

I agree.

ned-deily avatar Nov 15 '22 11:11 ned-deily