Python 3.13.x SSL security changes

I think I found the issue and understand why the steps you followed solved the issue.

In your first post, you only reference the root certificate for validation. Later, after you followed the guide and exported the certificates via chrome, you reference both the root certificate AND the intermediate certificate. In the intermediate certificate, the attribute X509v3 Basic Constraints is actually set to “critical”, in root it is not.

From RFC 5280: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile

Conforming CAs MUST include this extension in all CA certificates
that contain public keys used to validate digital signatures on
certificates and MUST mark the extension as critical in such
certificates.

So yes, the solution is to also include the intermediate certificate(s) in your trust chain, atleast for the current ZScaler certificates, as the intermediate cert has the correct attribute. I recommend to only include the first intermediate certificate along with the root cert, as it has a long validity in contrast to the second intermediate cert, which is only valid for ~2 weeks.

Here is how you can validate it yourself:

openssl x509 -text -noout -in zscaler_root.crt
...
 X509v3 Basic Constraints: 
     CA:TRUE
...
openssl x509 -text -noout -in zscaler_first_intermediate.crt
...
X509v3 Basic Constraints: critical
    CA:TRUE
...

And in Python:

>>> requests.get(some_url, verify="only_intermediate_1.crt")
<Response [200]>
>>> requests.get(some_url, verify="only_root.crt")
<ssl basic constraint not critical error>

Here is also the discussion where it was introduced in Python 3.13: `ssl`: changing the default `SSLContext.verify_flags`? - #15 by gpshead

1 Like