From: Vsevolod Stakhov Date: Thu, 16 Jul 2026 09:01:55 +0000 (+0100) Subject: [Fix] Aliases: refuse to rewrite From domains X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9fe6cb2aa05043890aea8f60eb18e28fce5ae622;p=thirdparty%2Frspamd.git [Fix] Aliases: refuse to rewrite From domains The From address is the sender's identity: SPF, DKIM and DMARC all key on its domain. Service rules and alias resolution (e.g. a virtual alias mapping to another domain) may only touch the local part of the From address; any rewrite that would change the domain is now discarded. Recipient rewriting is unaffected: recipients are interpreted by the receiving host, and no authentication protocol keys on them. Also fix a spurious task:set_from call: the set_from decision used the callback-wide alias_resolved flag, so a rewrite of any earlier address (e.g. an envelope recipient) caused the unmodified MIME From to be marked as aliased and duplicated. Issue: #6137 --- diff --git a/src/plugins/lua/aliases.lua b/src/plugins/lua/aliases.lua index 762957ba71..4514727219 100644 --- a/src/plugins/lua/aliases.lua +++ b/src/plugins/lua/aliases.lua @@ -340,6 +340,9 @@ local function aliases_callback(task) }) --- Check and resolve From address + -- The From address is the sender's identity: SPF, DKIM and DMARC all key on + -- its domain, so only the local part may be rewritten here; any rewrite that + -- would change the domain is discarded -- @param addr_type 'smtp' or 'mime' local function check_from(addr_type) if not task:has_from(addr_type) then @@ -347,12 +350,24 @@ local function aliases_callback(task) end local addr = task:get_from(addr_type)[1] - local original_addr = addr.addr + local original_domain = addr.domain + local modified = false + + local function same_domain(domain) + return domain and original_domain and + domain:lower() == original_domain:lower() + end -- Apply service-specific rules (Gmail, plus-aliases) if settings.enable_gmail_rules or settings.enable_plus_aliases then local nu, tags, nd = lua_aliases.apply_service_rules(addr) + if nd and not same_domain(nd) then + lua_util.debugm(N, task, 'refuse to rewrite %s from domain: %s -> %s', + addr_type, original_domain, nd) + nd = nil + end + if nu or nd then set_addr(addr, nu, nd) @@ -364,24 +379,30 @@ local function aliases_callback(task) end, tags) end - alias_resolved = true + modified = true end end -- Resolve through alias system local canonical = lua_aliases.resolve_address(addr, resolve_opts) - if canonical and canonical:lower() ~= original_addr:lower() then + if canonical and canonical:lower() ~= addr.addr:lower() then -- Update address local user, domain = canonical:match('^([^@]+)@(.+)$') if user and domain then - set_addr(addr, user, domain) - alias_resolved = true + if same_domain(domain) then + set_addr(addr, user, domain) + modified = true + else + lua_util.debugm(N, task, 'refuse to resolve %s from %s -> %s: domain change', + addr_type, addr.addr, canonical) + end end end -- Update in task - if alias_resolved then + if modified then task:set_from(addr_type, addr, 'alias') + alias_resolved = true end end