CVE-2026-90776
highPriorität · verfolgen · 30EPSS 0.007 · 52. PerzentilRUUSEPSS · bewertet 2026-10-27
Nodemailer versions 9.1.0 through 10.0.4 contain a quadratic time complexity vulnerability in the addressparser component when parsing email addresses with RFC 5322 comments. Attackers can craft malicious email headers with comment-separated atoms to consume excessive CPU and block the Node.js event loop for several seconds, causing denial of service.
cvss
Technischer Schweregrad, 0–10. Eine Zeile je Quelle.
Basiswert 0–10 · höher = schwerwiegender · Vektor überfahren zum Auflösen⚠ Quellen uneinig · medium–high · 6.6–8.7
SSVC
Eine Handlungsentscheidung — aus Ausnutzung und Auswirkung.
schwächen
Die CWE-Schwächeklassen, zu denen dies gehört.
betroffene Produkte (2)
Betroffene Produkte und Versionsbereiche.
Advisories (1)
Hersteller- und Ökosystem-Meldungen dazu.
- GHSA-prgh-xp8r-p3m5Nodemailer addressparser: O(n^2) on comment-joined addresses enables a remote DoS (reachable via mailparser)2026-09-30ghsa · osvUS
### 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`: ```js 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`): ```js 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`): ```js 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: ```js (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.
auch bekannt als (1)
Weitere Namen und Kennungen dieser Entität.
quellen
Welche Quellen diesen Datensatz belegen und wann.
Referenzen (6) nvd
Externe Belege — Patches, Meldungen, Analysen.
- https://github.com/nodemailer/nodemailer
- https://github.com/nodemailer/nodemailer/blob/v10.0.4/src/addressparser/index.ts#L251
- https://github.com/nodemailer/nodemailer/commit/c07f17518d25aca8ab2ad66968dcbca538c24b89
- https://github.com/nodemailer/nodemailer/releases/tag/v10.0.5
- https://github.com/nodemailer/nodemailer/security/advisories/GHSA-prgh-xp8r-p3m5
- https://www.vulncheck.com/advisories/nodemailer-9.1.0-through-10.0.4-denial-of-service-via-quadratic-address-parsing
Angreifer nutzen Schwachstellen wie diese gegen im Internet exponierte Dienste aus. Sehen Sie mit einem kostenlosen Passiv-Scan, was exponiert ist.
Kostenloser Scan