From: Vsevolod Stakhov Date: Thu, 16 Jul 2026 09:47:27 +0000 (+0100) Subject: [Fix] Forged recipients: compare addresses as they were transmitted X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f5d7db89db756deb986cd72329100d0614957e9e;p=thirdparty%2Frspamd.git [Fix] Forged recipients: compare addresses as they were transmitted The rule compared the rewritten envelope view against the wire MIME headers, so a recipient alias mapping to another domain (legal for recipients) could make a perfectly matching To header look forged. Compare the envelope and the headers at the same altitude: both as they were seen in the message, which is also what this rule checked before alias rewriting was applied to tasks. Issue: #6137 --- diff --git a/src/plugins/lua/forged_recipients.lua b/src/plugins/lua/forged_recipients.lua index 0d51db3920..8605e77139 100644 --- a/src/plugins/lua/forged_recipients.lua +++ b/src/plugins/lua/forged_recipients.lua @@ -37,8 +37,11 @@ local E = {} local function check_forged_headers(task) local auser = task:get_user() local delivered_to = task:get_header('Delivered-To') - local smtp_rcpts = task:get_recipients(1) - local smtp_from = task:get_from(1) + -- Compare the envelope and the headers as they were transmitted: alias + -- rewrites (e.g. a cross-domain virtual alias applied to the envelope + -- recipients) must not make the wire To/Cc headers look forged + local smtp_rcpts = task:get_recipients({ 'smtp', 'orig' }) + local smtp_from = task:get_from({ 'smtp', 'orig' }) if not smtp_rcpts then return @@ -144,7 +147,7 @@ local function check_forged_headers(task) -- Check sender if smtp_from and smtp_from[1] and smtp_from[1]['addr'] ~= '' then - local mime_from = task:get_from(2) + local mime_from = task:get_from({ 'mime', 'orig' }) if not mime_from or not mime_from[1] or not rspamd_util.strequal_caseless_utf8(mime_from[1]['addr'], smtp_from[1]['addr']) then task:insert_result(symbol_sender, 1, ((mime_from or E)[1] or E).addr or '', smtp_from[1].addr) diff --git a/test/functional/cases/001_merged/360_aliases.robot b/test/functional/cases/001_merged/360_aliases.robot index 26d4daaaa9..a341ab5596 100644 --- a/test/functional/cases/001_merged/360_aliases.robot +++ b/test/functional/cases/001_merged/360_aliases.robot @@ -184,3 +184,14 @@ FROM SAME-DOMAIN ALIAS - APPLIED ... Rcpt=user@example.com Expect Symbol ALIAS_RESOLVED Expect Symbol With Exact Options GET_FROM Abuse Desk,admin@example.com,admin,example.com + +RCPT CROSS-DOMAIN ALIAS - NOT FORGED + [Documentation] A recipient rewritten to another domain (allowed for + ... recipients) must not make the matching wire To header look forged: + ... forged_recipients compares the addresses as transmitted + Scan File ${RSPAMD_TESTDIR}/messages/aliases_rcpt_virtual.eml + ... From=sender@external.com + ... Rcpt=virtual@example.com + Expect Symbol ALIAS_RESOLVED + Do Not Expect Symbol FORGED_RECIPIENTS + Do Not Expect Symbol FORGED_SENDER diff --git a/test/functional/messages/aliases_rcpt_virtual.eml b/test/functional/messages/aliases_rcpt_virtual.eml new file mode 100644 index 0000000000..a246ccf141 --- /dev/null +++ b/test/functional/messages/aliases_rcpt_virtual.eml @@ -0,0 +1,8 @@ +From: Sender +To: virtual@example.com +Subject: Test cross-domain recipient alias vs forged recipients +Message-ID: +Date: Mon, 01 Jan 2025 10:00:00 +0000 + +A recipient rewritten to another domain must not make the wire To header +look forged.