-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Accessing unrelated extensions fails when BasicConstraints encodes default ca:FALSE #14592
Description
Accessing unrelated extensions fails when BasicConstraints encodes default ca:FALSE
Versions
- Python: 3.13.5
- cryptography: 46.0.6
- OS: Debian Trixie (amd64)
Description
When a certificate's BasicConstraints extension explicitly encodes ca:FALSE (the DER default value), the cryptography library raises a ValueError with ParseError { kind: EncodedDefault } when accessing any extension, not just BasicConstraints.
This means that calling cert.extensions.get_extension_for_class(SubjectAlternativeName) fails even though the SAN extension itself is perfectly valid. The error is thrown during iteration of the extensions list, making all extensions inaccessible.
The certificate is a real certificate observed in a Certificate Transparency log. OpenSSL parses it without errors and correctly shows CA:FALSE in the Basic Constraints and a valid SAN (DNS:receptum-apteekkiverkko.maxx.fi, IP Address:83.150.105.126).
While explicitly encoding the default value violates DER (the ca field defaults to FALSE per RFC 5280 and should be omitted), this encoding is common in the wild and is accepted by other implementations.
Minimal PoC
from cryptography import x509
der = open("entry_0046.der", "rb").read()
cert = x509.load_der_x509_certificate(der)
# This works fine:
print(cert.subject)
print(cert.issuer)
# This fails, even though SAN is valid:
san = cert.extensions.get_extension_for_class(x509.SubjectAlternativeName)Output:
Traceback (most recent call last):
File "poc.py", line 8, in <module>
san = cert.extensions.get_extension_for_class(x509.SubjectAlternativeName)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
ValueError: error parsing asn1 value: ParseError { kind: EncodedDefault, location: ["BasicConstraints::ca"] }
OpenSSL output
OpenSSL parses the same certificate without issue:
$ openssl x509 -inform DER -in entry_0046.der -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
01:99:3d:78:70:fe:f2:ca:f0:9b:b6:c9:d1:78:28
Signature Algorithm: sha512WithRSAEncryption
Issuer: C=FI, O=Digi- ja vaestotietovirasto CA, OU=Sosiaali- ja terveydenhuollon palveluvarmenteet, CN=DVV Social Welfare and Healthcare Service Certificates - G3R
Validity
Not Before: Oct 22 21:00:00 2025 GMT
Not After : Oct 22 20:59:59 2026 GMT
Subject: C=FI, ST=FINLAND, L=Naantali, O=Naantalin 2. apteekki, serialNumber=1.2.246.553.1.853.13.0, CN=83.150.105.126
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Alternative Name:
DNS:receptum-apteekkiverkko.maxx.fi, IP Address:83.150.105.126
(Full output omitted for brevity. The certificate is attached as entry_0046.pem.txt.)
Root cause
The BasicConstraints extension contains 30 03 01 01 00 — a SEQUENCE with an explicit BOOLEAN FALSE. Per DER, the ca field defaults to FALSE and must be omitted when it has the default value. The Rust ASN.1 parser in cryptography strictly rejects this as EncodedDefault. Since extension parsing is all-or-nothing, this makes every extension on the certificate inaccessible.
Expected behavior
Ideally, accessing an unrelated extension like SubjectAlternativeName should not fail due to a strict-DER violation in BasicConstraints. Possible approaches:
- Parse extensions lazily so that accessing one extension doesn't require successfully parsing all others.
- Accept the common DER violation of explicitly encoding default values in
BasicConstraints.