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



GHSA-2X7J-588G-CCC2

GHSA-2x7j-588g-ccc2: Algorithmic Complexity Denial of Service in Nodemailer

Amit Schendel
Amit Schendel
Senior Security Researcher

Sep 9, 2026·5 min read·1 visit

Executive Summary (TL;DR)

Nodemailer versions prior to 9.1.0 are vulnerable to remote Denial of Service (DoS) due to quadratic time complexity ($O(n^2)$) in the address parser and envelope generation modules, which blocks the single-threaded Node.js event loop.

An algorithmic complexity vulnerability in Nodemailer before version 9.1.0 allows remote attackers to block the Node.js event loop. This denial of service is triggered by processing large or complex lists of email addresses, leading to quadratic resource consumption.

Vulnerability Overview

Nodemailer is a widely adopted module for sending emails within Node.js applications. It relies on internal components such as the addressparser module and the mime-node engine to parse headers, format recipient lists, and construct SMTP-compliant envelopes. These components process inputs that are frequently sourced directly from untrusted clients, such as user registration forms, contact portals, or inbound mail relays.\n\nThe vulnerability arises due to inefficient algorithms implemented within these processing modules. When an application processes address fields containing thousands of elements or specifically structured fragments, the execution time increases quadratically rather than linearly. Because Node.js utilizes a single-threaded execution model, any prolonged synchronous execution blocks the main event loop entirely.\n\nWhile the event loop is blocked, the server cannot process any other incoming requests, network events, or database callbacks. This behavior transforms a standard string-parsing routine into an effective unauthenticated remote denial of service vector. The system remains completely unresponsive until the computation terminates or the node process is terminated by resource exhaustion limits.

Root Cause Analysis

The root cause is divided into three distinct architectural bottlenecks where algorithmic operations scale quadratically ($O(n^2)$) relative to the size of the input.\n\nThe first bottleneck is located in lib/addressparser/index.js during the accumulation of parsed addresses. The parser iterates over parsed address collections and combines them using Array.prototype.concat(). In JavaScript, concat() allocates a new array and copies all existing and new elements to it. Iterating this operation $N$ times over $N$ addresses results in a cumulative copying overhead of $O(n^2)$ complexity.\n\nThe second bottleneck exists within the display-name fragment recombination logic. To resolve unquoted display names containing commas, the parser iterates backward and executes Array.prototype.splice(i, 1) to merge fragments in place. Splicing elements shifts all subsequent elements in the array to fill the gap. For highly fragmented inputs, executing this operation recursively degrades performance quadratically.\n\nThe third bottleneck resides inside the mime-node envelope generator's _convertAddresses() function. To ensure unique recipients, the code executes Array.prototype.some() to scan the output list for existing records. Performing a linear array scan for every new address elements means that processing a list of $N$ recipients requires $O(n^2)$ comparisons. If these recipients are spread across multiple headers, the validation state is continuously rebuilt, exacerbating the performance penalty.

Execution Path and Complexity Bottlenecks

The following architectural flow illustrates how input processing escalates from a string parser to a blocked event loop:\n\nmermaid\ngraph LR\n A["Untrusted Address Input"] --> B["addressparser() Validation"]\n B --> C["Loop with Array.concat()"]\n B --> D["Loop with Array.splice()"]\n C --> E["O(N^2) Accumulation"]\n D --> E\n E --> F["MimeNode._convertAddresses()"]\n F --> G["Linear Array.some() Scan"]\n G --> H["O(N^2) Envelope Deduplication"]\n H --> I["Node.js Event Loop Blocked"]\n\n\nThis diagram outlines the sequential parsing steps and the precise points where the $O(n^2)$ complexity bottlenecks occur inside both addressparser and mime-node.

Code-Level Analysis and Patches

The vulnerabilities were remediated across three distinct performance-focused commits on August 31, 2026. The patches replace quadratic operations with linear alternatives.\n\nCommit 9116da9528c6524cefaed75185602a7e85d20434 resolves the address parser overhead. It replaces the concat accumulation with an in-place .push() loop, lowering allocation overhead to $O(1)$ per element. It also replaces the in-place splice with a single-pass merge accumulator array that is reversed at the end of the execution block:\n\njavascript\n// Vulnerable logic used concat and splice:\n// parsedAddresses = parsedAddresses.concat(handled);\n// parsedAddresses.splice(i, 1);\n\n// Patched logic uses pushing and a reverse operation:\nfor (let i = 0; i < handled.length; i++) {\n parsedAddresses.push(handled[i]);\n}\n\nconst mergedAddresses = [];\nfor (let i = parsedAddresses.length - 1; i >= 0; i--) {\n const current = parsedAddresses[i];\n const next = mergedAddresses.length ? mergedAddresses[mergedAddresses.length - 1] : null;\n if (next && current.address === '' && current.name && !current.group && next.address && next.name) {\n next.name = current.name + ', ' + next.name;\n } else {\n mergedAddresses.push(current);\n }\n}\nmergedAddresses.reverse();\nparsedAddresses = mergedAddresses;\n\n\nCommit 7cc38af418ffa6fc7e86085195ca5ca681694b3e addresses the envelope deduplication lookup overhead. The linear lookups via .some() are replaced with $O(1)$ lookups leveraging a native JavaScript Set:\n\njavascript\n// Patched logic utilizes Set for deduplication\nif (!seenAddresses) {\n seenAddresses = new Set();\n for (let i = 0; i < uniqueList.length; i++) {\n seenAddresses.add(uniqueList[i].address);\n }\n}\n\n// ...\nif (!seenAddresses.has(address.address)) {\n seenAddresses.add(address.address);\n uniqueList.push(address);\n}\n\n\nCommit 34da64282dcdc9b0581c721a27ab2fa226673150 fixes cross-header deduplication by instantiating the seenRecipients set once per envelope cycle instead of recreating it on each individual header call. This change ensures that multi-header emails scale linearly. These combined changes reduce the execution time for 100,000 addresses from over 25 seconds down to under 100 milliseconds.

Exploitation Methodology

Exploitation of this vulnerability requires no special authentication or privileges. The attack vector depends entirely on the application's ingestion of email address lists from untrusted inputs.\n\nAn attacker can construct a payload consisting of a large, comma-separated string containing redundant email addresses. Alternatively, the attacker can format a payload containing highly fragmented, unquoted names with commas to maximize the display-name splicing execution path. An example payload structure is shown below:\n\ntext\nTo: a, b <c@d.com>, a, b <c@d.com>, ... [repeated 50,000 times]\n\n\nWhen the application processes this payload, the Node.js process experiences 100% CPU utilization. Because Node.js is single-threaded, the entire process is blocked. Any health check endpoints will fail to respond, causing load balancers or container orchestrators to mark the service as unhealthy and terminate the container instance, resulting in service disruption.

Impact Assessment

The primary impact of this vulnerability is complete and immediate denial of service. Because the main thread is blocked, any active connections to the application are dropped or timed out, and no new connections can be established.\n\nThis vulnerability does not allow for privilege escalation, remote code execution, or information disclosure. The threat is strictly limited to availability, making it a high-impact reliability concern for production workloads handling mail queues or webhook events.\n\nThe CVSS v3.1 vector string is calculated as CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H, reflecting network-based, unauthenticated, low-complexity denial of service with high availability impact.

Official Patches

NodemailerPull Request containing performance improvements to address parsing and deduplication.

Fix Analysis (3)

Technical Appendix

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

Affected Systems

Applications utilizing Nodemailer versions prior to 9.1.0 that parse untrusted recipient or header arrays.

Affected Versions Detail

Product
Affected Versions
Fixed Version
nodemailer
Nodemailer
< 9.1.09.1.0
AttributeDetail
CWE IDCWE-400
Attack VectorNetwork (Unauthenticated)
CVSS Score7.5
EPSS Score0.00045
ImpactDenial of Service (DoS)
Exploit Statuspoc
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
CWE-400
Uncontrolled Resource Consumption

The system does not properly control the allocation and maintenance of resources, allowing an attacker to trigger quadratic resource consumption.

Known Exploits & Detection

GitHub AdvisoryOfficial GitHub Security Advisory describing the quadratic scaling behavior during address parsing.

Vulnerability Timeline

Vulnerability fixes committed to GitHub
2026-08-31
Nodemailer version 9.1.0 released containing patches
2026-08-31
GitHub Security Advisory published
2026-08-31

References & Sources

  • [1]GHSA-2x7j-588g-ccc2 Advisory
  • [2]Nodemailer Release v9.1.0

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

•about 2 hours ago•GHSA-WMMP-3585-3RMP
5.9

GHSA-WMMP-3585-3RMP: IDN/Punycode Domain Allow-list Bypass in Nodemailer

Nodemailer (prior to version 9.1.0) is vulnerable to an IDN/Punycode domain allow-list bypass due to an interpretation conflict between legacy RFC-3492 codecs and modern UTS-46 Unicode parsers.

Amit Schendel
Amit Schendel
2 views•6 min read
•about 3 hours ago•CVE-2026-86996
5.3

CVE-2026-86996: Missing Authorization in n8n AI Agent Workflow Tool Execution

A missing authorization vulnerability (CWE-862) exists in n8n where AI Agent workflows executing as tools bypass the Sub-Workflow Caller Policy settings, allowing authenticated users with agent creation privileges to invoke unauthorized sub-workflows across project boundaries.

Amit Schendel
Amit Schendel
6 views•6 min read
•about 4 hours ago•CVE-2026-83612
8.7

CVE-2026-83612: Algorithmic Complexity and Denial of Service via Output Amplification in xmldom

A Denial of Service (DoS) vulnerability exists in the xmldom library when parsing HTML-mode documents with mixed-case closing tags for raw-text or escapable raw-text elements like script, style, textarea, or title. This leads to algorithmic complexity issues and quadratic output amplification during DOM serialization.

Alon Barad
Alon Barad
5 views•6 min read
•about 5 hours ago•CVE-2026-78679
7.1

CVE-2026-78679: Arbitrary File Read via Command-Line Option Injection in GitPython

A command-line option injection vulnerability in GitPython allows low-privilege or unauthenticated actors to read arbitrary local files. The flaw resides in the TagReference.create() function, which fails to evaluate positional arguments against the library's unsafe-option denylist, enabling the execution of native git commands with injected option flags.

Amit Schendel
Amit Schendel
7 views•5 min read
•about 6 hours ago•CVE-2026-78677
7.5

CVE-2026-78677: Path Traversal and Arbitrary File Write in GitPython

GitPython prior to version 3.1.59 contains a path traversal vulnerability via parameter injection. The clone denylist did not restrict the `--separate-git-dir` option, allowing attackers to write repository metadata to arbitrary system paths.

Alon Barad
Alon Barad
6 views•6 min read
•about 7 hours ago•CVE-2026-72925
6.1

CVE-2026-72925: Cross-Site Scripting via Improper JSON Escaping in SWC HTML Minifier

CVE-2026-72925 is a critical vulnerability in the SWC HTML minifier (@swc/html and swc_html_minifier) where safe Unicode-escaped characters in embedded JSON script tags are normalized into raw, unescaped characters during optimization, causing browser-side HTML injection and Cross-Site Scripting.

Amit Schendel
Amit Schendel
6 views•7 min read