Public mode

No access to your tenant or devices. Every item links to its source. What this means

Some sources or documents need attention: 275/275 feeds/APIs · 469/469 docs · 9/9 advisories · checked 07:24 UTC Customize Public modeDiscuss ChangeIntel on Discord

Nodemailer 3.0.0 before 10.0.10 Quadratic DKIM Header Unfolding Denial of Service

Collected exploitation and prediction evidence

Risk source coverage

CISA KEV is observed exploitation evidence. FIRST EPSS is a dated prediction of exploitation in the next 30 days. Missing scores are unknown. This collector requests predictions only for explicit CVE aliases in the public NuGet archive; Microsoft release views retain their existing prediction scope.

No collected risk observation for these identifiers. This does not establish absence of exploitation or a zero probability.

cve-program · CVE-2026-110871

Published

Nodemailer from 3.0.0 before 10.0.10 contains a denial of service vulnerability in MessageParser.parseHeaders that allows users to exhaust CPU through quadratic header unfolding. Attackers can supply large recipient lists or long headers that fold into tens of thousands of continuation lines, blocking the Node.js event loop during DKIM signing.

Source published
14 Oct 2026 22:52:59 UTC
Source modified
20 Oct 2026 02:28:10 UTC
Observed here
23 Oct 2026 15:48:27 UTC
Source terms
CVE Program Terms of Use

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: cve-program · CVE Program Terms of Use. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 4.0 · 7.1 CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

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

euvd · EUVD-2026-101754

Published

Nodemailer from 3.0.0 before 10.0.10 contains a denial of service vulnerability in MessageParser.parseHeaders that allows users to exhaust CPU through quadratic header unfolding. Attackers can supply large recipient lists or long headers that fold into tens of thousands of continuation lines, blocking the Node.js event loop during DKIM signing.

EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON.

Original publisher date fields

datePublished: Oct 14, 2026, 10:52:59 PM

dateUpdated: Oct 20, 2026, 2:28:10 AM

Source published
Oct 14, 2026, 10:52:59 PM (timezone not stated)
Source modified
Oct 20, 2026, 2:28:10 AM (timezone not stated)
Observed here
7 Nov 2026 04:32:30 UTC
Source terms
ENISA EUVD · source terms and attribution apply

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: euvd · ENISA EUVD · source terms and attribution apply. Source text is retained; field grouping and change labels are provided by ChangeIntel.

EUVD CVSS 4.0 · 7.1 CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

nvd · CVE-2026-110871

Published

Nodemailer from 3.0.0 before 10.0.10 contains a denial of service vulnerability in MessageParser.parseHeaders that allows users to exhaust CPU through quadratic header unfolding. Attackers can supply large recipient lists or long headers that fold into tens of thousands of continuation lines, blocking the Node.js event loop during DKIM signing.

NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON.

Source analysis status: Awaiting Analysis

Weakness classifications: CWE-400

Original publisher date fields

published: 2026-10-14T23:17:28.953

lastModified: 2026-10-20T03:17:14.553

Source published
14 Oct 2026 23:17:28 UTC
Source modified
20 Oct 2026 03:17:14 UTC
Observed here
25 Oct 2026 05:17:13 UTC
Source terms
NIST NVD usage terms; underlying source attribution retained

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: nvd · NIST NVD usage terms; underlying source attribution retained. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 4.0 · [email protected] · Secondary · 7.1 CVSS:4.0/AV:N/AC:L/AT:N/PR:L/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

CVSS 3.1 · [email protected] · Secondary · 6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

osv · GHSA-39m8-27wv-hr27

Published

## Summary When nodemailer DKIM-signs an outbound message, its DKIM message parser unfolds RFC 5322 header continuation lines with a loop that concatenates each continuation line onto the preceding line and then re-tests the anchored regex `/^[ \t]/` against the growing merged line on every iteration. Re-testing the regex against the ever-growing accumulated line forces a full string flatten proportional to the accumulated length on each iteration, yielding O(n^2) CPU in the number of continuation lines. An application user who influences the size of a header that folds into many continuation lines (most naturally a large recipient list, but also a long custom header, Subject, or References) can drive tens of thousands of continuation lines and block the single-threaded Node.js event loop for seconds during signing, a repeatable denial of service. ## Root Cause The invariant that signing a message performs work linear in the message size is violated in the header-unfolding step. In `src/dkim/message-parser.ts`, `parseHeaders()` splits the buffered header block into `lines` and iterates backward; for each line matching the continuation pattern `/^[ \t]/`, it does `lines[i - 1] += '\n' + lines[i]` and `lines.splice(i, 1)`. The dominant cost is not the array splice: iterating backward keeps each splice near the shrinking tail, so it shifts only the few trailing header lines. The quadratic cost is the anchored regex test `/^[ \t]/.test(lines[i])` (together with the `+=` concatenation) evaluated against the growing merged line on every iteration. The `+=` builds an O(1) rope, but the next iteration's regex test forces a full flatten of the entire accumulated line, so the total cost is the sum over all continuation lines, which is O(n^2). The header block is buffered by `checkHeaders` without any size or line-count cap; the DKIM signer's `MAX_MESSAGE_SIZE` and `cacheTreshold` knobs gate the body stream only, not the header block, so nothing bounds the number of continuation lines fed to the loop. ```text Affected file and function (verified at the published v10.0.9 artifact, in src/ and compiled verbatim into the published dist output): - src/dkim/message-parser.ts: MessageParser.parseHeaders (the continuation-unfold loop that re-tests /^[ \t]/ against the growing merged line) ``` ## Impact An attacker or user who can make an outbound, DKIM-signed message carry a header that folds into a large number of continuation lines can freeze the sending Node.js process during signing. Because Node.js is single-threaded, the synchronous unfold loop starves the entire event loop, halting all other work in the process, and it is repeatable on every such message. The natural lever is a large recipient list: nodemailer's own MIME composer folds a To or Cc value at column 76 into space-prefixed continuation lines, and the count scales linearly with the number of recipients, so a caller-supplied recipient list (common in bulk-mail, notification, and multi-tenant email APIs) turns into tens of thousands of continuation lines. The single precondition is that DKIM signing is enabled, which is a mainstream deliverability configuration. Independent reproduction on Node.js 24 measured roughly 2.8 seconds of event-loop blocking at about 20,000 continuation lines and roughly 11.5 seconds at about 40,000, scaling quadratically; the full composer-to-signer chain with a 60,000-recipient To header blocked for roughly 6.6 seconds. The applications that cap recipient count or header size shrink the exposed population but do not change the per-message availability impact once a large header is accepted. ## Proof of Concept `Node.js 24; the shipped DKIM signer (require('nodemailer/lib/dkim')) or the exact unfold loop.` Steps: (1) construct a message whose header block contains one header value folded into many space-prefixed continuation lines (for example by supplying a very large recipient list, which nodemailer's MIME composer folds automatically); (2) DKIM-sign it and observe the event loop stall while `parseHeaders` unfolds the block. A minimal microbenchmark of the exact unfold logic demonstrates the complexity: ```js // Reproduces the parseHeaders unfold loop verbatim (Node 24). function unfold(headerBlock) { const lines = headerBlock.split(/\r?\n/); for (let i = lines.length - 1; i > 0; i--) { if (/^[ \t]/.test(lines[i])) { lines[i - 1] += '\n' + lines[i]; lines.splice(i, 1); } } return lines; } function run(n) { let block = 'To: [email protected]\r\n'; for (let i = 0; i < n; i++) block += ' cont-' + i + '@example.com,\r\n'; for (let k = 0; k < 5; k++) block += 'X-H' + k + ': v\r\n'; const t = Date.now(); unfold(block); return Date.now() - t; } for (const n of [5000, 10000, 20000, 40000]) console.log(n, run(n) + 'ms'); ``` ```text 5000 27ms 10000 542ms 20000 2853ms 40000 11503ms (2x input yields roughly 4x-5x time: quadratic. The cost is the regex re-flatten of the growing merged line, not the splice.) ``` ## Attack Chain 1. **Exposure:** An application DKIM-signs outbound mail (a mainstream deliverability configuration, enabled per transport or per message) for a message whose header size is influenced by a user, for example a large recipient list, a long custom header, Subject, or References. 2. **Control:** The attacker or user controls the size of that header. The MIME composer folds it deterministically at column 76 into space-prefixed continuation lines that match the continuation pattern, so the continuation-line count scales linearly with the supplied size. 3. **Path:** Signing pipes the composed message through the DKIM MessageParser; `checkHeaders` buffers the whole header block into `rawHeaders` and calls `parseHeaders()`, the single sink, on every signed message. 4. **Guard:** No header-size or line-count cap exists between the input and the sink; the signer's body-only size thresholds do not apply to the header block. 5. **Primitive:** The unfold loop re-tests the anchored regex against the growing merged line on each continuation line, forcing a full flatten per iteration and yielding O(n^2) synchronous CPU. 6. **Result:** Event-loop starvation of the single-threaded sending process for an attacker-scaled duration, repeatable per message: a denial of service. ## Bypass Evidence The relevant guard would be a cap on header-block size or continuation-line count before unfolding. A search of the DKIM module confirms none exists: `checkHeaders` accumulates header chunks unbounded until the header terminator, and the only size knobs (`MAX_MESSAGE_SIZE`, `cacheTreshold`) are checked against the body stream, not the header block. The strongest disproof attempt was that the backward `splice` makes the loop cheap for a single consecutive folded block (so it would not be quadratic); this was refuted by a mechanism-isolation benchmark: removing the splice entirely leaves the loop just as slow (about 11 seconds at 40,000 lines), while precomputing the continuation test on the original lines so the growing merged line is never re-tested collapses it to a few milliseconds. This proves the quadratic driver is the regex re-flatten of the accumulated line, not the array shift, and confirms the loop is quadratic even for a single consecutive folded block. No published advisory covers this file: the disclosed complexity issues all live in the address parser and recipient-normalization code, and the DKIM message parser has never received a complexity fix. ## Affected Versions - `Ecosystem: npm` - `Package: nodemailer` - `Confirmed affected range: <= 10.0.9` - `Latest release checked: nodemailer 10.0.9 (npm registry; vulnerable code verified at git tag v10.0.9 and in the published dist output)` - `Fix status: not fixed (no released version removes the quadratic unfold or caps header size)` The unfold loop is long-standing DKIM code that predates the address-parser complexity fix family, so the exact introducing release is not positively established and the lower bound is left open; the upper bound is verified against the current published artifact, which is vulnerable with no fix. ## Suggested Fix Enforce linear-time header unfolding and bound the header block. The key correction is to stop re-scanning the growing accumulated line: classify each line's continuation status on the original split lines before merging, and build the unfolded value with an array plus a single join rather than repeatedly re-testing and concatenating the growing string. Simply replacing `splice` with a filter or two-pointer compaction while still re-testing the merged line would not fix the issue, because the regex re-flatten of the accumulated line is the quadratic driver. Independently, impose a configurable maximum on the buffered header-block size or continuation-line count in the message parser and fail closed when it is exceeded, so an oversized folded header cannot force unbounded work. As an interim mitigation, applications should cap recipient counts and header-value sizes for messages that will be DKIM-signed. Reported by zx (GitHub: @manus-pi).

Source published
22 Oct 2026 16:07:04 UTC
Source modified
22 Oct 2026 16:15:47 UTC
Observed here
24 Oct 2026 13:17:17 UTC
Source terms
GitHub Advisory Database · CC-BY-4.0

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · GitHub Advisory Database · CC-BY-4.0. Source text is retained; field grouping and change labels are provided by ChangeIntel.

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

Publisher rating · MODERATE

osv · GHSA-wxxx-r42m-9rp8

Withdrawn

## Duplicate Advisory This advisory has been withdrawn because it is a duplicate of GHSA-39m8-27wv-hr27. This link is maintained to preserve external references. ## Original Description Nodemailer from 3.0.0 before 10.0.10 contains a denial of service vulnerability in MessageParser.parseHeaders that allows users to exhaust CPU through quadratic header unfolding. Attackers can supply large recipient lists or long headers that fold into tens of thousands of continuation lines, blocking the Node.js event loop during DKIM signing.

Source published
15 Oct 2026 00:31:19 UTC
Source modified
22 Oct 2026 16:15:48 UTC
Observed here
24 Oct 2026 13:17:17 UTC
Source terms
GitHub Advisory Database · CC-BY-4.0

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · GitHub Advisory Database · CC-BY-4.0. Source text is retained; field grouping and change labels are provided by ChangeIntel.

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

CVSS_V4 · CVSS:4.0/AV:N/AC:L/AT:N/PR:L/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

Publisher rating · HIGH

ChangeIntel

An IT change radar: releases, security, known issues, retirements, documentation changes, and service status from public sources. Every item links to supporting evidence; dates and statuses can change after they are read.

Sources read 8 Nov 07:24 UTC · 275 of 275 readable · 273 fully read · documentation 469/469 current