Aug 3, 2026·5 min read·206 visits
Unauthenticated remote attackers can cause complete CPU exhaustion and Denial of Service (DoS) on endpoints using python-cryptography by submitting malformed certificate chains containing duplicate self-signed intermediates, triggering an exponential path-building backtracking loop.
An uncontrolled resource consumption vulnerability (CWE-400) exists in the python-cryptography library's Rust-based X.509 verification engine. The flaw allows unauthenticated remote attackers to trigger severe CPU exhaustion and Denial of Service (DoS) by supplying specially crafted certificate chains containing duplicate self-signed certificates, forcing the recursive path builder into an exponential state-search loop.
The python-cryptography library utilizes a Rust-based path validation module, cryptography-x509-verification, to construct and validate certificate paths from an end-entity leaf certificate back to a trusted anchor.
This engine exposes a critical attack surface on any server, application, or gateway that accepts client certificates, validates S/MIME signatures, or performs custom X.509 validations on untrusted user-supplied certificate inputs.
The vulnerability is classified under CWE-400: Uncontrolled Resource Consumption. Under adversarial conditions, the verification engine is susceptible to algorithmic complexity exploitation, wherein a relatively short, maliciously structured validation chain triggers high CPU usage and complete system unavailability.
The path building process in ChainBuilder::potential_issuers functions by mapping subject names to find candidate parents from the trust store and the untrusted intermediate certificate pool.
Prior to version 49.0.0, when the pool of untrusted intermediates contained multiple identical or structurally identical copies of a self-signed certificate, the potential_issuers method retrieved and processed each duplicate independently.
Because the recursive function build_chain_inner failed to deduplicate these candidate issuers or bound the number of cryptographic signature operations, the resolver entered a recursive backtracking search. For $k$ duplicate intermediate certificates and a maximum path search depth $d$, the engine performs up to $k^d$ recursive states and corresponding signature validations. This combinatorial explosion quickly saturates the host CPU.
The vulnerability was resolved in commit 4a12cf49675a184e47f912b00b04f3a629283582 by implementing two complementary mitigation policies within the Rust engine.
First, a global signature validation budget of 128 check operations is introduced. Every signature verification decrements this budget, preventing unbound verification cycles. Second, candidate parent certificates are sorted and prioritized based on matching authority and subject key identifiers (AKI/SKI), pushing unlikely or duplicate name-colliding certificates to the bottom of the evaluation list.
Below is the structured representation of the path traversal workflow showing how validation flow has been bounded:
Let us review the key differences in src/rust/cryptography-x509-verification/src/lib.rs:
struct Budget {
name_constraint_checks: usize,
+ signature_checks: usize,
}
impl Budget {
+ const DEFAULT_SIGNATURE_CHECK_LIMIT: usize = 1 << 7; // Max 128 checks
+ fn signature_check<'chain, B: CryptoOps>(&mut self) -> ValidationResult<'chain, (), B> {
+ self.signature_checks = self.signature_checks.checked_sub(1).ok_or_else(|| {
+ ValidationError::new(ValidationErrorKind::FatalError(
+ "Exceeded maximum signature check limit",
+ ))
+ })?;
+ Ok(())
+ }
}The implementation of potential_issuers now performs a stable sort to group the most viable candidate issuers first, using AKI-to-SKI matching:
- fn potential_issuers(
- &self,
- cert: &'a VerificationCertificate<'chain, B>,
- ) -> impl Iterator<Item = &'a VerificationCertificate<'chain, B>> + '_ {
+ fn potential_issuers(
+ &self,
+ cert: &'a VerificationCertificate<'chain, B>,
+ cert_extensions: &Extensions<'chain>,
+ ) -> Vec<&'a VerificationCertificate<'chain, B>> {
+ let mut candidates: Vec<&'a VerificationCertificate<'chain, B>> = self
+ .store
+ .get_by_subject(&cert.certificate().tbs_cert.issuer)
+ .iter()
+ .chain(self.intermediates.iter().filter(|&candidate| {
+ candidate.certificate().subject() == cert.certificate().issuer()
+ }))
+ .collect();
+
+ let want_kid: Option<&[u8]> = cert_extensions
+ .get_extension(&AUTHORITY_KEY_IDENTIFIER_OID)
+ .and_then(|ext| ext.value::<AuthorityKeyIdentifier<'_, Asn1Read>>().ok())
+ .and_then(|aki| aki.key_identifier);
+
+ candidates.sort_by_key(|candidate| {
+ let have_kid: Option<&[u8]> =
+ candidate.certificate().extensions().ok().and_then(|exts| {
+ exts.get_extension(&SUBJECT_KEY_IDENTIFIER_OID)
+ .and_then(|ext| ext.value::<&[u8]>().ok())
+ });
+
+ match (want_kid, have_kid) {
+ (Some(want), Some(have)) if want == have => 0, // Match (high priority)
+ (Some(_), Some(_)) => 2, // Mismatch (low priority)
+ _ => 1u8, // Missing ID (medium priority)
+ }
+ });
+ candidates
+ }Exploitation does not require authentication or elevated privileges. An attacker simply submits a structured certificate chain containing several duplicates of a self-signed certificate.
Because the path validation engine explores all possible path combinations recursively, the CPU time increases exponentially relative to the number of duplicates. If the target server uses the unpatched verification engine, this process will block the executing thread indefinitely or until it hits a global worker timeout.
To demonstrate the vulnerability, the following performance table measures the validation duration of the unpatched vs. the patched library configuration:
| Duplicates | Max Search Depth | Unpatched Execution Time | Patched Execution Time |
|---|---|---|---|
| 1 | 7 | 0.00046 seconds | 0.00066 seconds |
| 2 | 7 | 0.02515 seconds | 0.00122 seconds |
| 3 | 7 | 0.48992 seconds | 0.00161 seconds |
| 4 | 7 | 4.30940 seconds | 0.00214 seconds |
| 3 | 8 | 1.46819 seconds | 0.00181 seconds |
| 4 | 8 | TIMEOUT (> 5.00s) | 0.00241 seconds |
| 5 | 7 | TIMEOUT (> 5.00s) | 0.00264 seconds |
| 6 | 6 | TIMEOUT (> 5.00s) | 0.00282 seconds |
Although the patch addresses the exponential explosion of cryptographic signature verification, some architectural edge cases remain.
First, potential_issuers continues to load and copy all matching intermediate certificates into a heap-allocated Vec before sorting. An attacker who uploads a chain with thousands of candidates can still force the server to allocate memory and perform $O(N \log N)$ operations. However, this is significantly less intensive than cryptographic signature operations.
Second, the name constraint budget of $2^{20}$ checks remains large. In highly complex, nested name constraint topologies, verification tasks could still introduce non-trivial latency overhead, though not sufficient to trigger a prolonged Denial of Service.
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
cryptography PyCA | < 49.0.0 | 49.0.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-400 |
| Attack Vector | Network (AV:N) |
| CVSS v4.0 Score | 8.7 (High) |
| Impact | Denial of Service (DoS) via CPU Exhaustion |
| Exploit Status | Proof-of-Concept (PoC) available |
| KEV Status | Not listed on CISA KEV |
The software does not properly control the allocation and maintenance of a limited resource, enabling an actor to influence the amount of resources consumed and leading to a denial of service.
An Server-Side Request Forgery (SSRF) vulnerability via DNS-Rebinding Time-of-Check to Time-of-Use (TOCTOU) has been discovered in SiYuan (思源笔记), an open-source personal knowledge management system. The flaw exists within the AI Agent tools http_request (util.HTTPRequest) and web_fetch (util.WebFetch) of the SiYuan Kernel, allowing unauthenticated remote attackers to bypass SSRF validation and access private internal services or cloud metadata endpoints.
An uncontrolled resource consumption vulnerability (CWE-1333 / CWE-400) exists in probe-image-size versions prior to 7.4.0. The SVG parser utilizes an unanchored, inefficient regular expression to find the SVG root tag, leading to catastrophic backtracking when handling malformed payloads. This blocks the single-threaded Node.js event loop, resulting in a complete denial of service.
CVE-2026-10032 is a DOM-based Cross-Site Scripting (XSS) vulnerability in Google's @a2ui/web_core Node.js library. The vulnerability is located within the openUrl utility function, which processes and opens dynamic URLs defined in layout configurations. Because the function fails to sanitize or validate the target URL scheme before passing it to the window.open browser sink, an attacker can specify a javascript: pseudo-protocol to execute arbitrary client-side script in the context of the host origin.
CVE-2026-59944 is a path traversal and link-following vulnerability in Composer, the PHP dependency manager. This flaw allows malicious or compromised packages to bypass previous path-hardening protections and perform arbitrary filesystem operations outside of their designated installation directory, leading to unauthorized permission modifications or execution proxy creations.
A critical Broken Object Level Authorization (BOLA) vulnerability was identified in Trigger.dev before version v4.5.2. An authenticated attacker could trigger a run replay and supply an arbitrary target environmentId belonging to a completely different tenant. Because the server failed to validate whether the target environment belonged to the same project or organization as the source run, it would execute the task within the victim's environment, resulting in unauthorized cross-tenant write operations and remote task execution.
A critical Server-Side Request Forgery (SSRF) vulnerability in Trigger.dev prior to version 4.5.2 allows authenticated organization members to configure webhook alert channels with unvalidated target URLs. This can lead to internal network scanning and cloud metadata extraction.