From: Alexander Moisseev Date: Mon, 30 Mar 2026 06:14:23 +0000 (+0300) Subject: [Fix] Skip HELO IP address literals for SPF domain resolution X-Git-Tag: 4.0.0~2^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=24eeb647a2d0f3cd0c784d541f4fa2afd7765b3b;p=thirdparty%2Frspamd.git [Fix] Skip HELO IP address literals for SPF domain resolution Per RFC 7208 §2.3, IP address literals (e.g. [192.0.2.1]) cannot be used as SPF domains. When MAIL FROM is empty, rspamd falls back to HELO as the SPF domain. With an IP literal in HELO, rspamd_spf_resolve() failed (DNS name rejected by the resolver), but spf_cred was non-NULL, so the result was incorrectly set to R_SPF_DNSFAIL instead of R_SPF_NA. Skip building spf_cred from HELO when it starts with '[', so rspamd_spf_get_cred() returns NULL and the result is R_SPF_NA. --- diff --git a/src/libserver/spf.c b/src/libserver/spf.c index 207a4ec3c7..e33b0f18d7 100644 --- a/src/libserver/spf.c +++ b/src/libserver/spf.c @@ -2674,7 +2674,7 @@ rspamd_spf_cache_domain(struct rspamd_task *task) if (!addr || (addr->flags & RSPAMD_EMAIL_ADDR_EMPTY)) { /* Get domain from helo */ - if (task->helo) { + if (task->helo && task->helo[0] != '[') { GString *fs = g_string_new(""); cred = rspamd_mempool_alloc(task->task_pool, sizeof(*cred)); @@ -2685,6 +2685,10 @@ rspamd_spf_cache_domain(struct rspamd_task *task) rspamd_mempool_add_destructor(task->task_pool, rspamd_gstring_free_hard, fs); } + else if (task->helo) { + /* IP address literals (e.g. [192.0.2.1]) cannot be used as SPF domain (RFC 7208 §2.3) */ + msg_info_task("skip SPF check for IP address literal in HELO: %s", task->helo); + } } else { rspamd_ftok_t tok; diff --git a/test/functional/cases/001_merged/117_spf.robot b/test/functional/cases/001_merged/117_spf.robot index a8b35a8c9d..199b50f1ee 100644 --- a/test/functional/cases/001_merged/117_spf.robot +++ b/test/functional/cases/001_merged/117_spf.robot @@ -50,6 +50,14 @@ SPF NA NXDOMAIN ... Settings=${SETTINGS_SPF} Expect Symbol R_SPF_NA +SPF NA HELO IP LITERAL + [Documentation] HELO IP address literals must yield R_SPF_NA, not R_SPF_DNSFAIL (RFC 7208 §2.3) + Scan File ${RSPAMD_TESTDIR}/messages/dmarc/bad_dkim1.eml + ... IP=8.8.8.8 From=<> Helo=[10.88.0.3] + ... Settings=${SETTINGS_SPF} + Expect Symbol R_SPF_NA + Do Not Expect Symbol R_SPF_DNSFAIL + SPF PERMFAIL UNRESOLVEABLE REDIRECT Scan File ${RSPAMD_TESTDIR}/messages/dmarc/bad_dkim1.eml ... IP=8.8.8.8 From=x@fail4.org.org.za