Error message
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: CA cert does not include key usage extension
Appears after upgrading to Python 3.13 or later; earlier versions do not set the strict flag. Followed by a source location such as "(_ssl.c:1082)". openssl verify -x509_strict reports the same check as "error 92 at 1 depth lookup: CA cert does not include key usage extension".
Python 3.13+ ssl module — VERIFY_X509_STRICT in create_default_context(), X509_V_ERR_CA_CERT_MISSING_KEY_USAGE (92)
What it means
Since Python 3.13, ssl.create_default_context() enables OpenSSL's strict X.509 checks (VERIFY_X509_STRICT). One of them requires every CA certificate to carry a keyUsage extension allowing certificate signing, as RFC 5280 demands. Your CA certificate has no keyUsage, so a chain that worked on Python 3.12 is now rejected even though the CA is explicitly trusted.
Why it happens
A CA created with a plain openssl req -x509
commonThe default OpenSSL configuration adds basicConstraints but no keyUsage to self-signed certificates. Countless guides create private CAs exactly this way, and so do some test fixtures and dev tools.
The client moved to Python 3.13 or newer
commonThe certificate did not change; the verifier became stricter. Container base images and CI runners that switch to python:3.13+ surface the problem without any change to the PKI.
Older internal PKI or appliance CAs
occasionalSome appliance-generated and older enterprise CA certificates omit keyUsage. They keep working in clients that do not apply strict checks.
How to fix it
- 1.
Confirm which extension is missing
Print the CA's basicConstraints and keyUsage, and run openssl verify -x509_strict to see every strict-mode failure at once.
bash openssl x509 -in ca.pem -noout -ext basicConstraints,keyUsage # Same strict checks as Python 3.13+, without Python: openssl verify -x509_strict -CAfile ca.pem server.pem - 2.
Reissue the CA certificate with keyUsage
Re-sign the CA with keyUsage = critical, keyCertSign, cRLSign (and basicConstraints critical). If you keep the same key and subject, certificates it already issued still chain to the new CA certificate; distribute the new CA file to clients.
bash # A CA certificate with the extensions RFC 5280 requires openssl req -x509 -new -key ca.key -days 3650 -subj "/CN=Example Private CA" \ -addext "basicConstraints=critical,CA:TRUE" \ -addext "keyUsage=critical,keyCertSign,cRLSign" \ -out ca.pem # Reusing the old key and subject keeps already issued certificates verifiable. - 3.
Temporary workaround: clear VERIFY_X509_STRICT for this context
Clearing the flag restores the Python 3.12 behaviour for one context. It is not the same as disabling verification, but it does accept certificates that violate RFC 5280; remove it once the CA is fixed.
python # Temporary workaround while the CA is reissued: the chain, dates and host name # are still verified, only the RFC 5280 profile checks are relaxed. import ssl ctx = ssl.create_default_context(cafile="ca.pem") ctx.verify_flags &= ~ssl.VERIFY_X509_STRICT
Related errors
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Basic Constraints o…Python 3.13+ ssl module[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Missing Authority K…Python 3.13+ ssl module[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local…Python ssl module (OpenSSL)