Package: release.debian.org Severity: normal Tags: trixie X-Debbugs-Cc: [email protected], [email protected] Control: affects -1 + src:node-nodemailer User: [email protected] Usertags: pu
[ Reason ] node-nodemailer is vulnerable due to improper handling of specially formatted recipient email addresses. [ Impact ] Medium vulnerability [ Tests ] Patch contains new tests [ Risks ] Low risk, test coverage is good and patch isn't complex [ Checklist ] [X] *all* changes are documented in the d/changelog [X] I reviewed all changes and I approve them [X] attach debdiff against the package in (old)stable [X] the issue is verified as fixed in unstable [ Changes ] Better address parsing Cheers, Xavier
diff --git a/debian/changelog b/debian/changelog index ba226b5..b4fb060 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +node-nodemailer (6.10.0+~6.4.17-1+deb13u1) trixie; urgency=medium + + * Fix addressparser handling of quoted nested email addresses + (Closes: CVE-2025-13033) + + -- Yadd <[email protected]> Sat, 15 Nov 2025 08:34:41 +0100 + node-nodemailer (6.10.0+~6.4.17-1) unstable; urgency=medium * New upstream version 6.10.0+~6.4.17 diff --git a/debian/patches/CVE-2025-13033.patch b/debian/patches/CVE-2025-13033.patch new file mode 100644 index 0000000..687b657 --- /dev/null +++ b/debian/patches/CVE-2025-13033.patch @@ -0,0 +1,141 @@ +Description: Fix addressparser handling of quoted nested email addresses +Author: Andris Reinman <[email protected]> +Origin: upstream, https://github.com/nodemailer/nodemailer/commit/1150d99f +Bug: https://github.com/nodemailer/nodemailer/security/advisories/GHSA-mm7p-fcc7-pg87 +Forwarded: not-needed +Applied-Upstream: 7.0.7, commit:1150d99f +Reviewed-By: Xavier Guimard <[email protected]> +Last-Update: 2025-11-15 + +--- a/lib/addressparser/index.js ++++ b/lib/addressparser/index.js +@@ -15,10 +15,12 @@ + address: [], + comment: [], + group: [], +- text: [] ++ text: [], ++ textWasQuoted: [] // Track which text tokens came from inside quotes + }; + let i; + let len; ++ let insideQuotes = false; // Track if we're currently inside a quoted string + + // Filter out <addresses>, (comments) and regular text + for (i = 0, len = tokens.length; i < len; i++) { +@@ -28,16 +30,25 @@ + switch (token.value) { + case '<': + state = 'address'; ++ insideQuotes = false; + break; + case '(': + state = 'comment'; ++ insideQuotes = false; + break; + case ':': + state = 'group'; + isGroup = true; ++ insideQuotes = false; ++ break; ++ case '"': ++ // Track quote state for text tokens ++ insideQuotes = !insideQuotes; ++ state = 'text'; + break; + default: + state = 'text'; ++ insideQuotes = false; + break; + } + } else if (token.value) { +@@ -51,8 +62,14 @@ + if (prevToken && prevToken.noBreak && data[state].length) { + // join values + data[state][data[state].length - 1] += token.value; ++ if (state === 'text' && insideQuotes) { ++ data.textWasQuoted[data.textWasQuoted.length - 1] = true; ++ } + } else { + data[state].push(token.value); ++ if (state === 'text') { ++ data.textWasQuoted.push(insideQuotes); ++ } + } + } + } +@@ -74,8 +91,12 @@ + // If no address was found, try to detect one from regular text + if (!data.address.length && data.text.length) { + for (i = data.text.length - 1; i >= 0; i--) { +- if (data.text[i].match(/^[^@\s]+@[^@\s]+$/)) { ++ // Security fix: Do not extract email addresses from quoted strings ++ // RFC 5321 allows @ inside quoted local-parts like "user@domain"@example.com ++ // Extracting emails from quoted text leads to misrouting vulnerabilities ++ if (!data.textWasQuoted[i] && data.text[i].match(/^[^@\s]+@[^@\s]+$/)) { + data.address = data.text.splice(i, 1); ++ data.textWasQuoted.splice(i, 1); + break; + } + } +@@ -92,10 +113,13 @@ + // still no address + if (!data.address.length) { + for (i = data.text.length - 1; i >= 0; i--) { +- // fixed the regex to parse email address correctly when email address has more than one @ +- data.text[i] = data.text[i].replace(/\s*\b[^@\s]+@[^\s]+\b\s*/, _regexHandler).trim(); +- if (data.address.length) { +- break; ++ // Security fix: Do not extract email addresses from quoted strings ++ if (!data.textWasQuoted[i]) { ++ // fixed the regex to parse email address correctly when email address has more than one @ ++ data.text[i] = data.text[i].replace(/\s*\b[^@\s]+@[^\s]+\b\s*/, _regexHandler).trim(); ++ if (data.address.length) { ++ break; ++ } + } + } + } +--- a/test/addressparser/addressparser-test.js ++++ b/test/addressparser/addressparser-test.js +@@ -309,4 +309,40 @@ + ]; + assert.deepStrictEqual(addressparser(input), expected); + }); ++ ++ // Security tests for RFC 5321/5322 quoted local-part handling ++ it('should not extract email from quoted local-part (security)', () => { ++ let input = '"[email protected] x"@internal.domain'; ++ let result = addressparser(input); ++ // Should preserve full address, NOT extract [email protected] ++ assert.strictEqual(result.length, 1); ++ assert.strictEqual(result[0].address.includes('@internal.domain'), true); ++ assert.strictEqual(result[0].address, '[email protected] [email protected]'); ++ }); ++ ++ it('should handle quoted local-part with attacker domain (security)', () => { ++ let input = '"[email protected]"@legitimate.com'; ++ let result = addressparser(input); ++ // Should route to legitimate.com, not attacker.com ++ assert.strictEqual(result.length, 1); ++ assert.strictEqual(result[0].address.includes('@legitimate.com'), true); ++ assert.strictEqual(result[0].address, '[email protected]@legitimate.com'); ++ }); ++ ++ it('should handle multiple @ in quoted local-part (security)', () => { ++ let input = '"a@b@c"@example.com'; ++ let result = addressparser(input); ++ // Should not extract a@b or b@c ++ assert.strictEqual(result.length, 1); ++ assert.strictEqual(result[0].address, 'a@b@[email protected]'); ++ }); ++ ++ it('should handle quoted local-part with angle brackets', () => { ++ let input = 'Name <"[email protected]"@example.com>'; ++ let result = addressparser(input); ++ assert.strictEqual(result.length, 1); ++ assert.strictEqual(result[0].name, 'Name'); ++ // When address is in <>, quotes are preserved as part of the address ++ assert.strictEqual(result[0].address, '"[email protected]"@example.com'); ++ }); + }); diff --git a/debian/patches/series b/debian/patches/series index 37d5831..40dc79a 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,3 +1,4 @@ drop-timeout-based-test.patch #fix-test-for-proxy-2.patch change-test-ports.patch +CVE-2025-13033.patch
-- Pkg-javascript-devel mailing list [email protected] https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/pkg-javascript-devel
