CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-86818

CVE-2026-86818: Mailto Header Injection via Percent-Encoded Field-Name Desynchronization in fast-uri

Amit Schendel
Amit Schendel
Senior Security Researcher

Sep 30, 2026·6 min read·23 visits

Executive Summary (TL;DR)

A validation discrepancy in fast-uri allows remote attackers to smuggle mailto parameters such as 'to', 'subject', and 'body' by using percent-encoded names like '%74o', bypassing safety validations before serialization.

A security-critical desynchronization vulnerability exists in fast-uri versions 4.1.3 and 4.1.4. Due to incorrect order-of-operations, the mailto scheme parser validates raw percent-encoded parameter keys instead of normalized keys, but subsequently decodes and writes them into a generic headers object. When the parsed URI is serialized, these keys are re-emitted literally, allowing attackers to bypass validation boundaries and smuggle unauthorized recipients, subjects, or body parameters in downstream mailing applications.

Vulnerability Overview

The npm package fast-uri is a dependency-free RFC 3986 URI parsing and serialization toolbox for Node.js. It serves as a performance-critical dependency for several high-volume ecosystem packages, including the Fastify web framework and the ajv JSON schema validator. In version 4.1.3, the package introduced a dedicated parser to handle the mailto URI scheme.

During its parsing operations, fast-uri separates standard, reserved mailto query parameters—specifically to, subject, and body—from user-defined, generic headers. This separation is critical for downstream applications that rely on the parsed output to validate email destinations and enforce local delivery policies before executing mail actions.

The vulnerability is classified under a combination of CWE-172 (Encoding Error) and CWE-436 (Interpretation Conflict). Because the library compares incoming query keys to reserved keys while they are still percent-encoded, it fails to recognize encoded reserved words. The subsequent decoding of these keys prior to internal storage creates an interpretation conflict between the validation phase and the serialization phase.

Root Cause Analysis

The root cause of this flaw lies in the sequencing of percent-decoding relative to token validation within the mailtoParse function. When processing a query parameter string such as ?%74o=attacker@evil.test, the parser extracts the key as %74o and compares it directly against string literals.

Because %74o does not literally match the string "to", the parser classifies the parameter as a generic, non-reserved header. However, during the storage phase, the parser executes decodeHex() on the key, which translates %74o to "to". This decoded key is then stored in a generic headers map as headers["to"] = "attacker@evil.test".

This discrepancy creates a desynchronization between the structured fields of the parsed object. An application auditing parsed.to will only observe the legitimate, safe recipients, while the malicious recipient remains hidden inside parsed.headers.to. When the object is passed to mailtoSerialize, the serializer loops over the keys of the headers map, encodes them, and appends them to the query string, re-emitting the literal to=attacker@evil.test parameter.

Code Analysis

A review of the vulnerable implementation in lib/schemes.js reveals the processing loop that causes the discrepancy:

// Vulnerable parsing logic in fast-uri v4.1.4
const name = eqIdx === -1 ? token : token.slice(0, eqIdx);
const value = eqIdx === -1 ? '' : token.slice(eqIdx + 1);
if (name === 'to') {
  const addrs = value.split(',');
  for (let j = 0; j < addrs.length; j++) to.push(addrs[j]);
  continue;
}
if (name === 'subject') {
  mailtoComponent.subject = decodeHex(value);
  continue;
}
if (name === 'body') {
  mailtoComponent.body = decodeHex(value);
  continue;
}
if (headers === null) headers = (Object.create(null));
headers[decodeHex(name)] = decodeHex(value);

In the block above, the variable name is compared to 'to', 'subject', and 'body' without prior decoding. If the attacker passes %74o, these comparisons evaluate to false. The execution path falls through to the final lines, where decodeHex(name) translates the key to 'to' and writes it into the headers dictionary.

The fix introduced in 4.1.5 corrects this by decoding the parameter name before performing any logic checks, while also adding lower-case normalization to prevent case-based bypasses (e.g., TO or To escaping detection):

// Corrected parsing logic in fast-uri v4.1.5
const name = decodeHex(eqIdx === -1 ? token : token.slice(0, eqIdx));
const normalizedName = name.toLowerCase();
const value = eqIdx === -1 ? '' : token.slice(eqIdx + 1);
if (normalizedName === 'to') {
  const addrs = value.split(',');
  for (let j = 0; j < addrs.length; j++) to.push(addrs[j]);
  continue;
}

Exploitation Methodology & Bypass Vector

Exploitation relies on a common software pattern: an application receives a URI, parses it to extract and validate properties, serializes the validated object back into a string, and then executes or transmits that string to a downstream system.

Consider an application that validates target email addresses against an internal allowlist. If the input is mailto:admin@company.com?%74o=attacker@evil.test, the validation system queries the parsed representation. The library returns parsed.to = ['admin@company.com'], which successfully matches the allowlist of @company.com.

// Conceptual application bypass flow
const parsed = fastURI.parse("mailto:admin@company.com?%74o=attacker@evil.test");
console.log(parsed.to); // ['admin@company.com'] -> Safe domain check passes
 
// Serialization generates the final payload
const finalURI = fastURI.serialize(parsed);
console.log(finalURI); // "mailto:admin@company.com?to=attacker@evil.test"

Because the verification logic only inspected the primary to array, the injected address hidden in headers.to bypassed the filter. Upon serialization, the library constructs a string containing two valid destination arguments, instructing the executing client to route the message to the unauthorized recipient.

Impact Assessment

The overall impact of CVE-2026-86818 depends heavily on the context of the downstream processing application. When used within automated registration, notification, or support-ticket workflows, this desynchronization allows attackers to force the sending of notifications to arbitrary accounts.

Attackers can leverage this bypass to intercept confidential emails by adding unauthorized CC or BCC entries. If the system constructs sensitive notifications containing password resets or system data, an attacker can append their email as a primary recipient through the serialized parameter injection.

The CVSS v3.1 vector is rated as 4.8 (Medium severity). Because exploitation requires a specific configuration where an application parses, validates, and subsequently re-serializes the mailto link prior to execution, the attack complexity is classified as High (AC:H). This vulnerability does not present opportunities for direct remote code execution or privilege escalation within the Node.js runtime itself.

Remediation & Patch Verification

To fully resolve CVE-2026-86818, developers must upgrade fast-uri to version 4.1.5 or later. This release addresses both the parsing order-of-operations and serialization canonicalization to ensure identical representations during both phases.

Because fast-uri is heavily utilized as a transitive dependency, standard direct updates may not immediately remediate nested packages. To enforce the updated library across the dependency tree, developers can utilize package manager overrides:

{
  "overrides": {
    "fast-uri": "^4.1.5"
  }
}

For environments where immediate updates are blocked, a manual mitigation policy must be implemented. Applications should sanitise user-supplied URIs by decoding and verifying all elements inside the nested headers object, or by stripping any occurrences of to, subject, or body from the headers map prior to serialization.

Fix Analysis (3)

Technical Appendix

CVSS Score
4.8/ 10
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N

Affected Systems

fast-uri versions 4.1.3 and 4.1.4Node.js applications parsing mailto schemas with fast-uriDownstream packages containing transient dependencies on fast-uri v4.1.3/v4.1.4, including Fastify and ajv

Affected Versions Detail

Product
Affected Versions
Fixed Version
fast-uri
Fastify / OpenJS Foundation
>= 4.1.3, <= 4.1.44.1.5
AttributeDetail
CWE IDCWE-172 / CWE-436
Attack VectorNetwork (AV:N)
CVSS v3.1 Score4.8
Exploitability Subscore2.2
Impact Subscore2.5
Exploit Statuspoc
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1566.002Phishing: Spearphishing Link
Initial Access
T1036Masquerading
Defense Evasion
CWE-436
Interpretation Conflict

The software processes data encoded in multiple formats and does not properly normalize or decode the payload before performing critical parsing operations, causing an interpretation mismatch between security validation and serialization.

Known Exploits & Detection

GitHub AdvisoryDetails on reproducing the parser desynchronization using percent-encoded parameters

References & Sources

  • [1]GHSA-jvvf-x445-j334: mailto header/parameter injection via percent-encoded field-name desynchronization
  • [2]NVD - CVE-2026-86818 Detail
  • [3]CVE.org Record - CVE-2026-86818
  • [4]OpenJS Foundation Security Advisories
  • [5]fast-uri Release v4.1.5
  • [6]Wiz Vulnerability Database: CVE-2026-86818

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•27 minutes ago•CVE-2026-62297
7.5

CVE-2026-62297: Uncontrolled Memory Allocation and Denial of Service in ag-psd

An uncontrolled memory allocation vulnerability exists in ag-psd versions prior to 31.0.0. When parsing Adobe Photoshop Document (PSD) files, the readPsd() function reads image dimensions and color depth directly from the file header and allocates off-heap typed arrays without validating whether the requested memory size is proportional to the input stream or bounded by operational thresholds. An unauthenticated attacker can supply a crafted 52-byte PSD payload that triggers an immediate 3.35 GB memory allocation, resulting in process termination via the operating system Out-Of-Memory (OOM) killer.

Amit Schendel
Amit Schendel
2 views•10 min read
•about 1 hour ago•CVE-2026-126297
7.5

CVE-2026-126297: Algorithmic Complexity Denial of Service in NLTK ConllCorpusReader

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).

Amit Schendel
Amit Schendel
3 views•12 min read
•about 2 hours ago•CVE-2026-126298
7.5

CVE-2026-126298: Quadratic Algorithmic Complexity Denial of Service in NLTK Tree.chomsky_normal_form

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.

Alon Barad
Alon Barad
6 views•12 min read
•about 3 hours ago•CVE-2026-126299
7.5

CVE-2026-126299: Quadratic Algorithmic Complexity Denial of Service in NLTK CCG Lexicon Parser

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.

Alon Barad
Alon Barad
5 views•10 min read
•about 4 hours ago•CVE-2026-126295
7.1

CVE-2026-126295: Path Traversal and Unconfined File Access in NLTK BllipParser

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.

Amit Schendel
Amit Schendel
2 views•11 min read
•about 5 hours ago•CVE-2026-126300
5.3

CVE-2026-126300: Algorithmic Complexity Denial of Service in NLTK TreebankWordTokenizer.span_tokenize

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.

Amit Schendel
Amit Schendel
3 views•10 min read