Skip to content

Accessing unrelated extensions fails when BasicConstraints encodes default ca:FALSE #14592

@st3fan

Description

@st3fan

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:

  1. Parse extensions lazily so that accessing one extension doesn't require successfully parsing all others.
  2. Accept the common DER violation of explicitly encoding default values in BasicConstraints.

entry_0046.pem.txt

Metadata

Metadata

Assignees

No one assigned

    Labels

    waiting-on-reporterIssue is waiting on a reply from the reporter. It will be automatically cloesd if there is no reply.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions