This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Error CERTIFICATE_VERIFY_FAILED in macOS
Type: Stage: resolved
Components: Library (Lib) Versions: Python 3.7, Python 3.6
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: christian.heimes, jaraco, ned.deily
Priority: normal Keywords:

Created on 2016-09-14 12:39 by jaraco, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (3)
msg276423 - (view) Author: Jason R. Coombs (jaraco) * (Python committer) Date: 2016-09-14 12:39
I saw the notice when installing Python 3.6.0b1 on Mac that said that the bundled OpenSSL is no longer used and thus 'certifi' will need to be installed and kept up-to-date.

At first, I thought, "no big deal" and pushed forward, but since, I've encountered the error in several cases:

- pip install of anything but certifi
- pip install in a new venv of anything but certifi
- distutils upload command (even with certifi installed)

I've only had 3.6.0b1 installed for a day, so I imagine I'm going to encounter new cases. Yes, indeed:

$ python
Python 3.6.0b1 (v3.6.0b1:5b0ca4ed5e2f, Sep 12 2016, 09:24:46) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib.request
>>> urllib.request.urlopen('https://www.google.com')
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/request.py", line 1318, in do_open
...
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ssl.py", line 683, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:747)

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.6/lib/python3.6/urllib/request.py", line 223, in urlopen
...
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/request.py", line 1320, in do_open
    raise URLError(err)
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:747)>
>>> import certifi


So it seems that even the guidance of installing certifi isn't sufficient to restore the basic expectation that using the stdlib to open URLs securely.

I can't imagine this behavior is acceptable (either requiring a bootstrap step in each environment or requiring some call at runtime to set up SSL before making HTTPS calls).

I no longer have the message that the installer gave me and I don't see anything in the What's New document for 3.6 about certificates.

Is this deficiency something that's planned to be corrected for the next beta? Is there a recommended procedure to enable SSL in urllib.request?
msg276424 - (view) Author: Christian Heimes (christian.heimes) * (Python committer) Date: 2016-09-14 12:45
We are not going to use certifi in rc and final releases. It's only in b1 because the infrastructure and cert handling code is not yet in place. Ned has a plan.
msg276516 - (view) Author: Ned Deily (ned.deily) * (Python committer) Date: 2016-09-15 05:34
Sorry, the information about this feature is currently only documented in the OS X installer ReadMe.  As you noted, it's displayed to the user during installation when using the OS X installer app.  A copy of the ReadMe is also installed for later reference in the directory /Applications/Python 3.6/.

Here's what it says about this feature:

========
Certificate verification and OpenSSL
------------------------------------

**NEW** This variant of Python 3.6 now includes its own private copy of OpenSSL 1.0.2.  Unlike previous releases, the deprecated Apple-supplied OpenSSL libraries are no longer used.  This also means that the trust certificates in system and user keychains managed by the Keychain Access application and the security command line utility are no longer used as defaults by the Python ssl module.  For 3.6.0b1, a sample command script is included in /Applications/Python 3.6 to install a curated bundle of default root certificates from the third-party certifi package (https://pypi.python.org/pypi/certifi).  If you choose to use certifi, you should consider subscribing to the project's email update service to be notified when the certificate bundle is updated.

The bundled pip included with the Python 3.6 installer has its own default certificate store for verifying download connections.
========

So the feature does *not* require 'certifi' to be installed.  As currently implemented, the supplied private copy of the OpenSSL libs is configured with its own private openssl directory for root certificates, as root certificates in macOS / OS X are stored in system and user keychains, not in an OpenSSL-compatible file or directory.  The path to the Python-installed directory is accessible via the attributes of ssl.get_default_verify_paths().  As installed, the Python-installed directory is empty.  So, to supply default root certificates, you need to either copy a certificate bundle or directory to the directory or provide a symlink to a certificate bundle or directory installed elsewhere.  In 360b1 as noted in the ReadMe, there is a simple double-clickable or command-line-runnable script ("/Applications/Python 3.6/Install Certificates.command") that does two things: 1. uses pip to install certifi and 2. creates a symlink in the OpenSSL directory to certifi's installed bundle location. Without the second step, installing certifi manually won't work, as you discovered.  Running the script as described in the ReadMe will solve your problem.  Of course, anyone can supply their own certificates as with any version of OpenSSL.

Granted, the 360b1 ReadMe could be more detailed.  For 360b2, I intend to expand the script to cover some other options and expand the documentation as part of Issue17128.  What's in 360b1 is not all that pretty but it seemed to me to be the least bad of the various practical options, including continuing to use the old, deprecated system OpenSSL libraries.
History
Date User Action Args
2022-04-11 14:58:36adminsetgithub: 72337
2016-09-15 05:34:21ned.deilysetstatus: open -> closed
priority: critical -> normal
type: security ->
messages: + msg276516

resolution: not a bug
stage: resolved
2016-09-14 12:46:56christian.heimessetpriority: normal -> critical
type: crash -> security
2016-09-14 12:45:56christian.heimessetnosy: + christian.heimes, ned.deily
messages: + msg276424
2016-09-14 12:39:30jaracocreate