python package does not depend on ca-certificates

Bug #1879310 reported by Christian Heimes
14
This bug affects 1 person
Affects Status Importance Assigned to Milestone
python3-defaults (Debian)
Fix Released
Unknown
python3.6 (Ubuntu)
New
Undecided
Unassigned
Bionic
New
Undecided
Unassigned
Focal
New
Undecided
Unassigned
python3.8 (Ubuntu)
New
Undecided
Unassigned
Bionic
New
Undecided
Unassigned
Focal
New
Undecided
Unassigned
python3.9 (Ubuntu)
New
Undecided
Unassigned
Bionic
New
Undecided
Unassigned
Focal
New
Undecided
Unassigned

Bug Description

(Affects all Python versions)

Python has no dependency on ca-certificates. Installing Python on a minimal Debian or Ubuntu container image does not pull in ca-certificates. This results in certificate validation issues as no trust anchors are available. Python's ssl module and ssl.create_default_context() depend on default root CA packages being available.

Since Python 2.7.9 and 3.4.0 the ssl module encourages developers to use ssl.create_default_context() to create a working and securely configured SSL context object. The implementation assumes that the platform has a correctly configured OpenSSL libssl that can load the default trust anchors (root CA certificates) with SSL_CTX_set_default_verify_paths().

Reproducer:

# docker run -ti ubuntu:bionic /bin/bash
# apt-get update
# apt-get install -y python3

# ls -la /etc/ssl/certs/ca-certificates.crt
ls: cannot access '/etc/ssl/certs/ca-certificates.crt': No such file or directory
# dpkg -l ca-certificates
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-===============-============-============-=================================
un ca-certificates <none> <none> (no description available)

# python3 -c 'from urllib.request import urlopen; urlopen("https://www.python.org")'
Traceback (most recent call last):
...
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:852)>
# echo $?
1

# apt-get install -y ca-certificates
# python3 -c 'from urllib.request import urlopen; urlopen("https://www.python.org")'
root@seneca:/# echo $?
0

Proposed solution:
Either all Python interpreter packages or libssl should pull in ca-certificates.

I have reported the bug on Debian's bug tracker as well, https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=960869

Changed in python3-defaults (Debian):
status: Unknown → New
Revision history for this message
Christian Heimes (heimes) wrote :

Latest Ubuntu release is still broken:

$ cat Dockerfile.ubuntu-groovy
FROM ubuntu:groovy
RUN apt update && \
    apt upgrade -y && \
    apt install -y python3 && \
    apt clean

RUN python3 -c 'from urllib.request import urlopen; urlopen("https://www.pypi.org")'

$ podman build -f Dockerfile.ubuntu-groovy
STEP 1: FROM ubuntu:groovy
STEP 2: RUN apt update && apt upgrade -y && apt install -y python3 && apt clean
--> Using cache 199e6b47bba512fbf9ffe7b308da61d7d0262c741d624ebfacea6b277cef2fbd
--> 199e6b47bba
STEP 3: RUN python3 -c 'from urllib.request import urlopen; urlopen("https://www.pypi.org")'
Traceback (most recent call last):
  File "/usr/lib/python3.8/urllib/request.py", line 1350, in do_open
    h.request(req.get_method(), req.selector, req.data, headers,
  File "/usr/lib/python3.8/http/client.py", line 1255, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib/python3.8/http/client.py", line 1301, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.8/http/client.py", line 1250, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.8/http/client.py", line 1010, in _send_output
    self.send(msg)
  File "/usr/lib/python3.8/http/client.py", line 950, in send
    self.connect()
  File "/usr/lib/python3.8/http/client.py", line 1424, in connect
    self.sock = self._context.wrap_socket(self.sock,
  File "/usr/lib/python3.8/ssl.py", line 500, in wrap_socket
    return self.sslsocket_class._create(
  File "/usr/lib/python3.8/ssl.py", line 1040, in _create
    self.do_handshake()
  File "/usr/lib/python3.8/ssl.py", line 1309, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1124)

The issue can be fixed with a simple one-line change to debian/control to install ca-certificates by default. curl has the same recommends stanza.

    Package: python3.8
    ...
    Recommends: ca-certificates

Revision history for this message
Christian Heimes (heimes) wrote :

Other language bindings pull in ca-certificates by default. PHP either depends on ca-certificates through apache2 -> ssl-cert -> openssl or php-curl -> libcurl bindings. Ruby has an indirect dependency while nodejs has a direct dependency.

# apt install ruby
# aptitude why ca-certificates
i ruby Depends ruby2.7
i A ruby2.7 Depends rubygems-integration (>= 1.8)
i A rubygems-integration Depends ca-certificates

Revision history for this message
Christian Heimes (heimes) wrote :

Reminder: It's been over 18 months since I reported this bug. python3 3.6.7-1~18.04 (bionic) and python3 3.8.2-0ubuntu2 (focal) are still not fixed. The bugfix is a trivial one-line change, which I mentioned in comment #1 over 13 months ago.

Changed in python3-defaults (Debian):
status: New → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.