Advisories for Npm/Nodemailer package

2026

Nodemailer: resolveContent() on a MailMessage bypasses disableFileAccess/disableUrlAccess when called with the legacy signature

Nodemailer's disableFileAccess / disableUrlAccess options are a security sandbox that lets an application forbid untrusted message content (html/text/attachment path/href) from reading local files or making outbound HTTP(S) requests. The fix for GHSA-wqvq-jvpq-h66f (commit 5f69497) threaded these flags through the library's internal resolution paths (MailMessage.resolveAll() and _convertDataImages()), but the public plugin API MailMessage.resolveContent(…args) (lib/mailer/mail-message.js:41-43) remains a raw passthrough to shared.resolveContent(). When called with the documented legacy signature mail.resolveContent(data, key, callback), shared.resolveContent …

Nodemailer: Recipient-domain validation bypass via RFC 5322 comment mis-parsing leads to email delivery to an attacker-controlled domain

Nodemailer's email-address parser treats an RFC 5322 comment ( … ) inside the domain as a point to concatenate the surrounding text, rather than as folding whitespace (CFWS) that terminates the domain. Consequently a recipient address such as user@good-corp.com(x)evil.com is parsed and delivered to good-corp.comevil.com (registrable domain comevil.com, attacker‑controlled), while a conformant RFC 5322 parser terminates the domain at the comment and reads good-corp.com. An application that decides whether it …

Nodemailer: Quadratic (O(n²)) time complexity in addressparser allows remote denial of service via a crafted address list

Nodemailer's address parser (lib/addressparser/index.js) parses a list of comma‑separated addresses in quadratic time — O(n²) in the number of addresses. A single crafted address string (e.g. a To, Cc, Bcc, From, or Reply‑To value, or any value passed to the exported addressparser) therefore consumes CPU proportional to the square of its length and blocks Node's single‑threaded event loop for the entire duration, denying service to every other request in the …

Nodemailer: IDN/Punycode domain allow-list bypass leads to email delivery to an attacker-controlled domain

Nodemailer resolves an international (IDN / non-ASCII) recipient domain to a different Punycode xn– label than every UTS‑46‑conformant parser (web browsers, the WHATWG URL Standard, Node's url.domainToASCII, Python's idna). Its address normalizer (_normalizeAddress in lib/mime-node/index.js) uses the bundled raw RFC‑3492 Punycode codec with no UTS‑46 mapping/normalization, so a domain that a standards‑compliant validator maps to a trusted domain is delivered by Nodemailer to a different, attacker‑registrable domain. An application that …

Nodemailer: Message-level raw option bypasses disableFileAccess/disableUrlAccess, enabling arbitrary file read and full-response SSRF in the delivered message

Nodemailer exposes disableFileAccess and disableUrlAccess so an application that passes untrusted message data to the library can forbid that data from reading local files or fetching URLs. Every attachment, alternative, html/text/watchHtml/amp and icalEvent content node honors these flags. The message-level raw option does not. MailComposer.compile() builds the root MIME node for a raw message without threading the two flags, so a raw: { path: '/etc/passwd' } or raw: { href: …

Nodemailer: Improper TLS Certificate Validation in OAuth2 Token Fetch Enables Credential Interception

Nodemailer disables TLS certificate verification in its internal HTTPS fetch client through the use of rejectUnauthorized: false inside lib/fetch/index.js. As a result, OAuth2 token requests trust invalid or self-signed HTTPS certificates and transmit sensitive OAuth credentials over connections that should fail TLS validation. An attacker in a machine-in-the-middle position can intercept OAuth2 credential exchanges and capture: OAuth client_secret refresh_token access tokens The issue was verified through runtime testing using a …

Nodemailer: CRLF injection in Nodemailer List-* header comments allows arbitrary message header injection

Nodemailer constructs List-* headers from the caller-provided list message option using internally prepared header values. The list.*.comment field is inserted into those prepared values without removing CR (\r) or LF (\n) characters. Because prepared headers bypass the normal header-value sanitizer and are passed to mimeFuncs.foldLines(), a CRLF sequence in a list comment is emitted as an actual header boundary in the generated RFC822 message. An application that lets a lower-privileged …

Nodemailer jsonTransport bypasses disableFileAccess and disableUrlAccess during message normalization

Nodemailer's disableFileAccess and disableUrlAccess options are intended to prevent message content and attachments from reading local files or fetching URLs. The normal MIME streaming path enforces those options in MimeNode._getStream(). However, jsonTransport serializes messages by calling mail.normalize(), which resolves html, text, alternatives, calendar events, and attachments through shared.resolveContent() before MIME generation. shared.resolveContent() reads local files and fetches HTTP(S) URLs directly, without receiving or checking disableFileAccess or disableUrlAccess. As a result, …

Nodemailer Vulnerable to SMTP Command Injection via CRLF in Transport name Option (EHLO/HELO)

Nodemailer versions up to and including 8.0.4 are vulnerable to SMTP command injection via CRLF sequences in the transport name configuration option. The name value is used directly in the EHLO/HELO SMTP command without any sanitization for carriage return and line feed characters (\r\n). An attacker who can influence this option can inject arbitrary SMTP commands, enabling unauthorized email sending, email spoofing, and phishing attacks.

2025

Nodemailer: Email to an unintended domain can occur due to Interpretation Conflict

The email parsing library incorrectly handles quoted local-parts containing @. This leads to misrouting of email recipients, where the parser extracts and routes to an unintended domain instead of the RFC-compliant target. Payload: "xclow3n@gmail.com x"@internal.domain Using the following code to send mail const nodemailer = require("nodemailer"); let transporter = nodemailer.createTransport({ service: "gmail", auth: { user: "", pass: "", }, }); let mailOptions = { from: '"Test Sender" <your_email@gmail.com>', to: "&#34;xclow3n@gmail.com …

2024
2021
2020