]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] URL: Prevent false positives from numeric IP regeneration in mailto URLs
authorVsevolod Stakhov <vsevolod@rspamd.com>
Tue, 6 Jan 2026 18:21:36 +0000 (18:21 +0000)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Tue, 6 Jan 2026 18:21:36 +0000 (18:21 +0000)
Fixes #5823 - Google Fonts URLs containing wght@0 parameter were incorrectly triggering URL_NUMERIC_IP and URL_BACKSLASH_PATH due to the @ symbol being interpreted as an email pattern and "0" being expanded to "0.0.0.0".

Also fix URL_BACKSLASH_PATH to actually check for backslashes instead of relying on the ambiguous obscured flag.

src/libserver/url.c
src/plugins/lua/url_suspect.lua

index 26d3b310a7aff4f78bf7cea9b0058e7166b6ea90..723d508edea8a11e62777713d7a1c2d9c84478af 100644 (file)
@@ -2651,19 +2651,22 @@ rspamd_url_parse(struct rspamd_url *uri,
                                }
 
                                if (all_chars_domain) {
-                                       /* Additionally check for a numeric IP as we can have some number here... */
-                                       rspamd_url_maybe_regenerate_from_ip(uri, pool);
+                                       /* Additionally check for a numeric IP as we can have some number here */
+                                       /* Skip for mailto: as email domains cannot be numeric IPs (see #5823) */
+                                       if (uri->protocol != PROTOCOL_MAILTO) {
+                                               rspamd_url_maybe_regenerate_from_ip(uri, pool);
+
+                                               if (last_c == '.' && uri->hostlen > 1) {
+                                                       /* Skip the last dot */
+                                                       uri->tldlen = uri->hostlen - 1;
+                                               }
+                                               else {
+                                                       uri->tldlen = uri->hostlen;
+                                               }
 
-                                       if (last_c == '.' && uri->hostlen > 1) {
-                                               /* Skip the last dot */
-                                               uri->tldlen = uri->hostlen - 1;
+                                               uri->tldshift = uri->hostshift;
+                                               is_whole_hostname_tld = true;
                                        }
-                                       else {
-                                               uri->tldlen = uri->hostlen;
-                                       }
-
-                                       uri->tldshift = uri->hostshift;
-                                       is_whole_hostname_tld = true;
                                }
                        }
 
index ec65c824250af5a01292dab74d0e43a49036f4c7..9d1a33f3a6d555c022402e4693a86826ce2c869b 100644 (file)
@@ -517,11 +517,15 @@ function checks.structure_analysis(task, url, cfg)
 
   -- Check backslashes using existing obscured flag
   if cfg.check_backslash and bit.band(flags, url_flags_tab.obscured) ~= 0 then
-    lua_util.debugm(N, task, "URL contains backslashes")
-    table.insert(findings, {
-      symbol = symbols.backslash,
-      options = { host or "obscured" }
-    })
+    local url_text = url:get_text()
+    -- We check if we *really* have backslashes here as obscured flag is ambiguous
+    if url_text and url_text:find('\\', 1, true) then
+      lua_util.debugm(N, task, "URL contains backslashes")
+      table.insert(findings, {
+        symbol = symbols.backslash,
+        options = { host or "obscured" }
+      })
+    end
   end
 
   -- Only get full URL text if length/@ checks are enabled (expensive for long URLs)