Skip to content

ssl.create_default_context(): add VERIFY_X509_STRICT and VERIFY_X509_PARTIAL_CHAIN to the default verify_flags #107361

Closed
@woodruffw

Description

@woodruffw

Feature or enhancement

My proposal is to add two new flags to the SSLContext.verify_flags created within ssl.create_default_context():

  1. VERIFY_X509_STRICT: This will enable stricter RFC 5280 compliance checks within OpenSSL's X.509 path validation implementation. This will have no effect on the overwhelming majority of users (since the overwhelming majority of TLS connections are likely going through the Web PKI, which is already much stricter than RFC 5280).
  2. VERIFY_X509_PARTIAL_CHAIN: This will allow OpenSSL's path validation to terminate at the first certificate listed in the user's root of trust, even if that certificate is not self-signed. Despite the confusing name and the fact that this isn't the default, this is the correct behavior per the various X.509 RFCs (3280, 5280): a trust anchor is defined to be an a priori trust relationship with a subject and its public key, regardless of whether the anchor comes in certificate form or is signed by another member of the trusted store. This should have no breaking effect on any users, but may cause some validations to produce shorter chains than the current SSLContext enables.

My proposal is consistent with the stability policy for create_default_context, which says that CPython may introduce changes to the default context without a prior deprecation period:

The protocol, options, cipher and other settings may change to more restrictive values anytime without prior deprecation. The values represent a fair balance between compatibility and security.

As with previous changes to the default context (such as the removal of 3DES support with 3.6), these proposed changes will not prevent people from constructing their own SSLContext without these new flags. In other words: users who do experience breakage or other behavioral changes will have a well-trodden alternative available to them, one that is documented as a matter of policy.

Pitch

To summarize from DPO:

  • Enabling VERIFY_X509_STRICT is a net security win: it reduces the amount of flexibility in the X.509 certificates that the ssl module accepts by default, which means less attacker controlled flexibility. It also makes CPython itself more compatible with the X.509 profile defined in RFC 5280, meaning that end-users can more confidently expect interoperation with PKIs that use the 5280 profile.
  • Enabling VERIFY_X509_PARTIAL_CHAIN makes ssl comply more closely with other path validation/building implementations (like Go's), and eliminates an error mode that's only possible because of OpenSSL's non-standard default behavior (a chain is built to the root of trust successfully, but can still fail because OpenSSL can't find a self-signed root also within the root of trust). It's also consistent with what curl and other downstream consumers of OpenSSL do.

Previous discussion

See DPO discussion here: https://discuss.python.org/t/ssl-changing-the-default-sslcontext-verify-flags/30230

Linked PRs

Metadata

Metadata

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions