Aug 3, 2026·6 min read·144 visits
A flaw in python-cryptography's Rust-based X.509 verifier allows a wildcard SAN (e.g., `*.example.com`) to satisfy a restricted permitted Name Constraint (e.g., `foo.example.com`), enabling subordinate CA scope escape.
An improper certificate validation vulnerability (CWE-295) in the Rust-based X.509 verification engine of python-cryptography allows wildcard Subject Alternative Names (SANs) to bypass permitted Name Constraints. This enables an attacker to construct certificates that escape the restricted scope of a subordinate Certificate Authority (CA) and successfully authenticate against vulnerable client installations. The vulnerability is tracked as CVE-2026-69248 and GHSA-m2h6-j472-rp4c, with a CVSS v4.0 base score of 6.9.
In public key infrastructure (PKI) deployments governed by RFC 5280, intermediate or subordinate Certificate Authorities (sub-CAs) can be bound to specific namespaces using the Name Constraints extension. This restriction is critical for delegated trust models, ensuring that a sub-CA managed by a specific department or external entity can only issue valid certificates for a predefined whitelist of domains (permittedSubtrees) or is prevented from issuing certificates for a blacklist of domains (excludedSubtrees).
The target of this vulnerability is the cryptography-x509-verification crate, which serves as the high-performance Rust-based validation engine for the Python cryptography library. When a client application validates a certificate path using this engine, the verifier must verify that every name present in the leaf certificate's Subject Alternative Name (SAN) extension strictly conforms to the name constraints configured on all upstream intermediate certificates in the trust chain.
Prior to version 49.0.0, the validation engine failed to correctly implement the Name Constraints verification logic when evaluating wildcard DNS SANs (such as *.example.com) against a permittedSubtrees constraint. An attacker capable of obtaining certificates from a constrained sub-CA could generate a certificate with an over-broad wildcard SAN, which the vulnerable engine would incorrectly accept as valid. This flaw exposes any TLS client or certificate-verification service relying on python-cryptography to trust boundary escapes and downstream spoofing.
The root cause of this vulnerability lies in the implementation of the DNSConstraint::matches method inside the cryptography-x509-verification module. Prior to the fix, this single function was utilized unconditionally to validate both permittedSubtrees and excludedSubtrees rules. The internal logic of matches evaluated whether there was any overlap between the constraint pattern and the wildcard SAN.
While an overlap-based validation model is mathematically and logically correct for excludedSubtrees (where any intersection between a blocked pattern and an issued name must trigger a validation failure to preserve safety), it is structurally insecure for permittedSubtrees. Under RFC 5280 §4.2.1.10, a wildcard SAN is only permitted if every potential domain name that the wildcard can represent falls strictly within the permitted subtree.
For example, if a sub-CA is constrained to the permittedSubtrees domain foo.example.com, and a leaf certificate contains the wildcard SAN *.example.com, the old verifier evaluated if foo.example.com overlapped with *.example.com. Because the wildcard pattern can expand to match the constraint, the function returned true, and the verifier erroneously trusted the certificate. However, *.example.com can also expand to bar.example.com or admin.example.com, both of which lie entirely outside the permitted constraint of foo.example.com. The engine therefore accepted a certificate that asserted authority over sibling domains outside the sub-CA's delegated boundary.
The patch resolves the vulnerability by introducing a structured separation between permitted and excluded evaluations. The unified DNSConstraint::matches method was completely deprecated and replaced with two explicit methods: permits and excludes. To track the context, a SubtreeKind enum was introduced.
// Introduced enum to differentiate evaluation behavior
#[derive(Clone, Copy)]
enum SubtreeKind {
Permitted,
Excluded,
}During verification, the engine now dispatches on the SubtreeKind to apply the appropriate mathematical rule. For permittedSubtrees, the engine calls permits, which mandates strict containment via the internal contains helper. This ensures that a wildcard is only allowed if its base domain is fully enclosed by the constraint.
impl<'a> DNSConstraint<'a> {
// Verifies if the constraint name contains the target name per RFC 5280
fn contains(&self, name: &DNSName<'_>) -> bool {
name.as_str().len() >= self.0.as_str().len()
&& self
.0
.rlabels()
.zip(name.rlabels())
.all(|(a, o)| a.eq_ignore_ascii_case(o))
}
// Enforces strict containment for permittedSubtrees
pub fn permits(&self, pattern: &DNSPattern<'_>) -> bool {
match pattern {
DNSPattern::Exact(name) => self.contains(name),
DNSPattern::Wildcard(base) => self.contains(base),
}
}
// Retains overlap logic for excludedSubtrees
pub fn excludes(&self, pattern: &DNSPattern<'_>) -> bool {
match pattern {
DNSPattern::Exact(name) => self.contains(name),
DNSPattern::Wildcard(base) => pattern.matches(&self.0) || self.contains(base),
}
}
}This division ensures that *.example.com is rejected when evaluated against foo.example.com because the base example.com does not fall within the subdomain foo.example.com. However, when evaluating exclusions, the overlap detection in excludes correctly identifies and blocks any intersection.
To exploit this vulnerability, an attacker must have access to a subordinate CA that is restricted by name constraints. This setup is typical in large corporate environments, federated identity systems, and cloud environments where sub-CAs are delegated to business units but restricted to specific subdomains to prevent inter-departmental spoofing.
The attacker requests a leaf certificate from the restricted sub-CA. While the sub-CA's name constraint extension restricts it to restricted-department.enterprise.com, the attacker requests a certificate containing a wildcard SAN such as *.enterprise.com. Due to the vulnerability, the sub-CA's signing system (if running the vulnerable library) or any downstream client application utilizing python-cryptography will validate the chain successfully.
Once the certificate is issued and trusted, the attacker can leverage it to conduct transparent Adversary-in-the-Middle (AiTM) decryption and spoofing. Any python-cryptography client attempting to connect to critical-billing.enterprise.com will accept the attacker's forged certificate without producing validation errors. This allows the attacker to hijack TLS sessions and harvest sensitive communications.
The security implications of CVE-2026-69248 are significant for organizations utilizing multi-tenant PKI architectures. If trust boundaries between tenants rely on Name Constraints, the vulnerability breaks the isolation model. An attacker can leverage a low-privilege sub-CA to masquerade as higher-privileged administrative or financial endpoints under the same parent domain.
Because python-cryptography is the underlying engine for major Python web frameworks, client libraries, and security orchestration tools, the impact of this vulnerability is amplified. For instance, any custom script performing TLS certificate validation or microservice routing that uses standard Python verification pipelines on vulnerable nodes can be manipulated.
With a CVSS v4.0 score of 6.9, the vulnerability is classified as Medium severity. This rating reflects the requirement for an active PKI architecture using Name Constraints (Attack Requirements: Present) and the need for the attacker to have issuance capabilities on the constrained sub-CA. However, in environments where these conditions are met, the integrity impact is high, as certificate validation trust guarantees are fully bypassed.
The primary remediation strategy is upgrading python-cryptography to version 49.0.0 or higher. This version integrates the patched Rust-based validation module which correctly separates permitted and excluded matching logic.
pip install --upgrade "cryptography>=49.0.0"For systems where immediate upgrading is not possible, security administrators should audit their PKI configuration. Intermediate CAs configured with Name Constraints must be monitored. Ensure that no certificates are issued containing wildcard SANs that are broader than the permitted subtrees defined in the issuing CA's configuration.
To verify the running package version programmatically within a deployment, the following python snippet can be integrated into system startup checks:
import cryptography
from packaging import version
current_version = cryptography.__version__
if version.parse(current_version) < version.parse("49.0.0"):
raise RuntimeError(f"Vulnerable cryptography package detected: {current_version}")| Product | Affected Versions | Fixed Version |
|---|---|---|
cryptography pyca | < 49.0.0 | 49.0.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-295 |
| Attack Vector | Network |
| CVSS v4.0 | 6.9 (Medium) |
| EPSS Score | Not yet indexed |
| Impact | High (Complete Bypass of Certificate-Based Trust Boundaries) |
| Exploit Status | poc |
| KEV Status | Not Listed |
A critical security vulnerability has been identified and patched in the WebUI component of pyLoad, a popular Python-based open-source download manager. This vulnerability allows attackers to completely bypass API rate limits and spoof client IP addresses in audit logs due to unsafe parsing of the X-Forwarded-For HTTP header.
An authorization bypass and credential oracle vulnerability in pyload-ng allows authenticated users with minimal or no privileges to brute-force the administrator password. This is achieved through sensitive API methods exposed globally combined with a non-constant-time password hash comparison algorithm.
An authentication bypass vulnerability in pyLoad allows unauthenticated remote attackers to gain administrative API access. The vulnerability is caused by a logical flaw in the API key cache validation lookup, where authentication states are cached using only the public key identifier, skipping cryptographic token verification on cache hits.
An authorization bypass vulnerability in Strawberry GraphQL between versions 0.217.0 and 0.326.1 occurs when a synchronous permission handler returns an awaitable object (such as an unawaited coroutine). Due to Python's truthiness rules, the unawaited coroutine is evaluated as True, leading to an immediate bypass of security policies.
An uncontrolled resource consumption vulnerability in Strawberry GraphQL allows unauthenticated remote attackers to trigger a Denial of Service on persistent WebSocket connections using the legacy graphql-ws protocol. When the server enforces max_subscriptions_per_connection, naturally terminating subscriptions are not cleared from memory registries, leading to exhaustion of connection slots.
A high-severity type-confusion vulnerability exists in NearForm fast-jwt prior to version 6.3.0. The vulnerability allows attackers to bypass crucial claim validation steps (such as expiration, issuer, audience, and subject validations) by presenting a validly signed JSON Web Token structured as a JSON array instead of a JSON object. This occurs because the library's decoder fails to reject JSON arrays during type evaluation.