Sep 30, 2026·4 min read·27 visits
An incorrect sequence of case folding and percent-decoding in fast-uri allows attackers to bypass case-sensitive domain filters using percent-encoded uppercase hostnames in scheme-relative URLs.
CVE-2026-86472 is a validation bypass vulnerability in fast-uri (a high-performance RFC 3986 URI toolbox heavily used by popular Node.js frameworks like Fastify and validation libraries like AJV). The vulnerability stems from improper handling of case sensitivity (CWE-178) due to an incorrect order of operations during hostname canonicalization in scheme-relative URLs. An attacker can leverage percent-encoded uppercase characters within scheme-relative URLs to bypass domain blocklists/allowlists in downstream applications. Because hostname resolution in DNS and HTTP is case-insensitive, the bypassed host representation still routes to the target destination, resulting in potential Server-Side Request Forgery (SSRF) or security control bypasses.
The vulnerability CVE-2026-86472 is an improper handling of case sensitivity (CWE-178) within the fast-uri library, an RFC 3986 compliant URI parser written for Node.js environments. The library serves as a critical performance-oriented dependency for parsing tasks in popular web frameworks and validation engines, including Fastify and AJV. The attack surface is exposed primarily when downstream systems process, validate, or perform routing decisions on user-supplied URLs.
Because hostname matching and resolving are inherently case-insensitive, a vulnerability arises when parsing and security filtering do not normalize capitalization in an identical fashion. The flaw allows external actors to submit specifically formatted URIs that bypass standard string-matching list validations, while still resolving to targeted servers. This discrepancy can compromise validation barriers, potentially permitting unintended network exposure or unauthorized access paths.
The flaw is located within the canonicalization workflow of the parser function (parseWithStatus inside index.js), specifically during the handling of hostnames in scheme-relative URLs. RFC 3986 requires that registered names (hostnames) be case-insensitive and folded to lowercase. It also specifies that percent-encoded unreserved characters, such as %41 representing 'A', should be decoded to their literal equivalents.
In the vulnerable codebase, the host lowercasing fold was executed prior to the percent-decoding sequence. Consequently, the percent-encoding identifier %41 remained unchanged by the lowercasing pass since it does not contain uppercase alphabetical characters. When the subsequent percent-decoding step ran, it converted %41 into its literal ASCII representation 'A', leaving an uppercase character in the parsed hostname.
This parsed output is structurally invalid according to lowercase normalization requirements, yet resolves correctly at the DNS or network routing level. Furthermore, this canonicalization logic was conditionally executed only within scheme-specific validation blocks. When parsing a scheme-relative URI (e.g., //%41.com), the absence of a scheme bypassed the secondary normalization checks, preserving the casing inconsistency.
The vulnerable logic in index.js checks for a scheme handler before applying host percent-decoding and normalization. This design omitted scheme-relative URLs from consistent parsing:
if (!schemeHandler || (schemeHandler && !schemeHandler.skipNormalize)) {
if (uri.indexOf('%') !== -1) {
if (parsed.host !== undefined && !malformedIPLiteral) {
const host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true)
parsed.host = reescapeHostDelimiters(host, isIP)
}
}
}The fix extracts the percent-decoding check outside of the scheme handler validation block, executing it unconditionally. The normalization process was also reordered to ensure case folding occurs after decoding:
if (uri.indexOf('%') !== -1 && parsed.host !== undefined && !malformedIPLiteral) {
let host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true)
if (!isIP) {
// Fold reg-name case after decoding unreserved octets.
host = normalizePercentEncoding(host.toLowerCase())
}
parsed.host = reescapeHostDelimiters(host, isIP)
}This ensures that any percent-encoded unreserved characters are first decoded to their literal forms, then folded to lowercase, and finally normalized to restore valid percent-escapes.
Exploitation requires that an application parses an input URI, validates the parsed host against an allowlist or denylist using case-sensitive operations, and subsequently uses the original or parsed URL to make an HTTP request. The attacker crafts a scheme-relative URI containing percent-encoded uppercase letters matching characters in a restricted domain.
When the application evaluates A.com against a case-sensitive blocklist containing a.com, the match fails, allowing the request to proceed. The downstream HTTP client then performs case-insensitive resolution, routing the request to a.com anyway.
The primary risk associated with this vulnerability is the evasion of domain-based access controls, leading to security filter bypasses such as Server-Side Request Forgery (SSRF). If an application restricts outbound connections using an allowlist parsed by fast-uri, an attacker can bypass this protection to access internal endpoints.
This vulnerability has a CVSS v3.1 base score of 4.8 (Medium), reflecting high attack complexity and low impact on confidentiality and integrity. No active exploitation has been observed, and the exploit status remains at proof-of-concept level.
Remediation requires upgrading fast-uri to version 2.4.7, 3.1.8, or 4.1.5, depending on the active branch. These versions contain the refactored parsing logic that resolves the order-of-operations conflict.
Where immediate upgrades are not feasible, developers must manually fold parsed hostnames to lowercase before performing string validation. This mitigation prevents differential interpretations between the application's business logic and the network layer.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
fast-uri fastify | < 2.4.7 | 2.4.7 |
fast-uri fastify | 3.0.0 - 3.1.7 | 3.1.8 |
fast-uri fastify | 4.0.0 - 4.1.4 | 4.1.5 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-178 |
| Attack Vector | Network (AV:N) |
| CVSS Score | 4.8 |
| EPSS Score | 0.00253 |
| Exploit Status | poc |
| CISA KEV Status | Not Listed |
The software performs a case-sensitive comparison or manipulation of an identifier that is meant to be case-insensitive, leading to security filter evasion.
CVE-2026-126297 (GHSA-v8f3-6phw-6mh9) is an uncontrolled resource consumption and algorithmic complexity vulnerability in the Natural Language Toolkit (NLTK) prior to version 3.10.4. Located in the Semantic Role Labeling (SRL) parser within `nltk/corpus/reader/conll.py`, the flaw allows an attacker to trigger quadratic O(N^2) CPU processing overhead by providing crafted CoNLL-formatted corpus inputs containing decoy span columns or nested full-width verb spans. Applications parsing untrusted linguistic corpora can experience prolonged CPU exhaustion and application-level Denial of Service (DoS).
CVE-2026-126298 (also tracked as GHSA-r53h-rw34-8h97) is an algorithmic complexity Denial of Service (DoS) vulnerability in the Natural Language Toolkit (NLTK) Python library affecting all versions prior to 3.10.4. The vulnerability resides in the nltk.tree.transforms.chomsky_normal_form function and its corresponding public method Tree.chomsky_normal_form(). When transforming a parse tree into Chomsky Normal Form using the default right-factoring strategy, the function repeatedly invokes list.pop(0) inside a loop iterating over all children of a node. In CPython, removing the initial element of a standard list requires an O(N) memory shift operation, causing the overall binarization algorithm to degrade to O(N^2) quadratic time complexity relative to the width of a node. Furthermore, converting horizontal node width into vertical tree depth bypasses initial parsing depth bounds, triggering subsequent stack exhaustion (RecursionError) when recursive methods traverse the mutated structure. Unauthenticated remote attackers who can submit bracketed tree strings to applications invoking this transformation can exhaust single-threaded CPU resources or induce unhandled application exceptions.
An algorithmic complexity vulnerability (CWE-407) in the Natural Language Toolkit (NLTK) before version 3.10.4 allows remote unauthenticated attackers to cause a denial of service via crafted Combinatory Categorial Grammar (CCG) lexicon strings. The parser in nltk.ccg.lexicon.fromstring performs repeated immutable string slicing, concatenation, and regex tail capturing, resulting in O(n^2) CPU consumption when processing wide, flat category definitions.
CVE-2026-126295 (also tracked as GHSA-fg9w-wfp5-j933) is a path confinement bypass vulnerability in the Natural Language Toolkit (NLTK) affecting versions 3.10.0 prior to 3.10.4. The flaw resides in nltk/parse/bllip.py within the BllipParser class and its factory method BllipParser.from_unified_model_dir(). Unlike sibling tool wrappers in NLTK that enforce data-root confinement via the nltk.pathsec module, BllipParser passes caller-supplied filesystem paths directly into the third-party bllipparser native C extension without validation. When an application passes untrusted input as model paths or directories to BllipParser, an attacker can force the native extension to open arbitrary files on the local filesystem. This leads to information disclosure through parser diagnostic oracles, local model tampering via shared directories, and denial of service by hanging worker threads on blocking special files (such as FIFOs or device nodes) or exhausting memory via oversized files.
CVE-2026-126300 (GHSA-ffr9-mgrr-wcvr) is an inefficient algorithmic complexity vulnerability (CWE-407) in the Natural Language Toolkit (NLTK) Python library affecting versions 3.2.5 prior to 3.10.4. The flaw resides in the quote-restoration routine of TreebankWordTokenizer.span_tokenize and NLTKWordTokenizer.span_tokenize, where repeated calls to list.pop(0) over matched quote tokens introduce quadratic O(n^2) time complexity. An unauthenticated remote attacker who supplies input containing long sequences of double-quote characters can exhaust CPU resources and degrade service availability.
The Natural Language Toolkit (NLTK) versions 3.6 through 3.10.3 contain an algorithmic complexity vulnerability in the LegalitySyllableTokenizer.tokenize method. When processing tokens composed of continuous runs of vowels, an unguarded string reversal and set membership lookup loop executes in quadratic time relative to the input token length. Remote attackers capable of submitting arbitrary text to applications utilizing this tokenizer can trigger sustained single-core CPU exhaustion and application-level denial of service.