]> git.ipfire.org Git - thirdparty/rspamd.git/log
thirdparty/rspamd.git
4 weeks agoMerge pull request #5948 from rspamd/vstakhov-exim-headers
Vsevolod Stakhov [Wed, 25 Mar 2026 08:39:21 +0000 (08:39 +0000)] 
Merge pull request #5948 from rspamd/vstakhov-exim-headers

[Feature] Expose milter headers in legacy RSPAMC protocol

4 weeks ago[Fix] Backport fixes from libucl
Vsevolod Stakhov [Wed, 25 Mar 2026 08:32:38 +0000 (08:32 +0000)] 
[Fix] Backport fixes from libucl

- ucl_msgpack: add bounds check after switch in ucl_msgpack_parse_ignore
  to prevent heap-buffer-overread when len is modified by fixext types
- ucl_sexp: fix broken length parsing, correct bounds check direction,
  add null pointer checks, fix memory leaks in error paths

5 weeks ago[Feature] Add worker:get_mem_config() Lua method for jemalloc stats 5949/head
Vsevolod Stakhov [Tue, 24 Mar 2026 08:44:35 +0000 (08:44 +0000)] 
[Feature] Add worker:get_mem_config() Lua method for jemalloc stats

Exposes structured jemalloc information via mallctl() as a nested table:
- stats: allocated, active, metadata, resident, mapped
- config: narenas, dirty_decay_ms, muzzy_decay_ms, tcache,
  background_thread, malloc_conf
- version: jemalloc version string
Returns nil when jemalloc is not compiled in.

5 weeks agoMerge pull request #5950 from moisseev/dependabot
Vsevolod Stakhov [Sun, 22 Mar 2026 14:36:53 +0000 (14:36 +0000)] 
Merge pull request #5950 from moisseev/dependabot

[Project] Disable npm dependency version update checks

5 weeks ago[Project] Disable npm dependency version update checks 5950/head
Alexander Moisseev [Sat, 21 Mar 2026 15:01:56 +0000 (18:01 +0300)] 
[Project] Disable npm dependency version update checks

5 weeks ago[Minor] Tune jemalloc for single-threaded multi-process architecture
Vsevolod Stakhov [Sat, 21 Mar 2026 14:37:53 +0000 (14:37 +0000)] 
[Minor] Tune jemalloc for single-threaded multi-process architecture

Set narenas:1 (one arena sufficient without threads), dirty_decay_ms:5000
(return dirty pages faster than default 10s), and muzzy_decay_ms:30000
(hold lazy-release pages for 30s before returning to OS).

5 weeks ago[Fix] Fix use-after-free in pending regexp map and multipattern queues
Vsevolod Stakhov [Sat, 21 Mar 2026 13:53:12 +0000 (13:53 +0000)] 
[Fix] Fix use-after-free in pending regexp map and multipattern queues

When a map reloads while awaiting async hyperscan compilation, the old
re_map/mp is destroyed but rspamd_regexp_map_add_pending (and its
multipattern counterpart) blindly appended a new entry without removing
the stale one. The linear search in find_pending then returned the first
(dangling) pointer, causing a heap-buffer-overflow in rspamd_snprintf
when accessing re_map->re_digest.

Fix by replacing existing entries with the same name in-place instead of
appending duplicates.

5 weeks ago[Minor] Optimize fuzzy_tcp_refresh_timeout
Vsevolod Stakhov [Sat, 21 Mar 2026 13:40:21 +0000 (13:40 +0000)] 
[Minor] Optimize fuzzy_tcp_refresh_timeout

Use ev_timer_again instead of stop/set/start triple, reducing three
libev calls to one. Move timeout refresh out of the write loop so it
is called once after draining the queue rather than on every write().

5 weeks ago[Fix] Fix CPU busy-loop in fuzzy TCP client due to EV_WRITE not being cleared
Vsevolod Stakhov [Sat, 21 Mar 2026 13:36:18 +0000 (13:36 +0000)] 
[Fix] Fix CPU busy-loop in fuzzy TCP client due to EV_WRITE not being cleared

When the TCP write queue drained, EV_WRITE was left armed on the socket
watcher. Since a connected TCP socket is always writable, libev fired
EV_WRITE continuously causing 100% CPU usage. The UDP path correctly
switched to EV_READ only after writing.

- Drop EV_WRITE when write queue empties in fuzzy_tcp_write_handler
- Only arm EV_WRITE on connection established if data is actually queued
- Remove redundant per-IO fuzzy_tcp_check_pending_timeouts call (timer
  callback already handles this), which amplified the spin with O(N)
  hash scans and GHashTable allocations on every iteration

5 weeks agoMerge pull request #5946 from moisseev/autolearnstats
Vsevolod Stakhov [Sat, 21 Mar 2026 13:26:16 +0000 (13:26 +0000)] 
Merge pull request #5946 from moisseev/autolearnstats

[Feature] Add rspamadm autolearnstats subcommand

5 weeks ago[Test] Add functional tests for legacy protocol milter headers 5948/head
Vsevolod Stakhov [Sat, 21 Mar 2026 12:12:10 +0000 (12:12 +0000)] 
[Test] Add functional tests for legacy protocol milter headers

Tests RSPAMC and SPAMC protocol output for:
- X-Milter-Add: lines (add headers)
- X-Milter-Del: lines (remove headers)
- X-Symbol: lines (extended symbol info with options)
- Backward compatibility of existing Symbol: lines

Also fix rspamc()/spamc() test helpers to read full response
instead of truncating at 2048 bytes.

5 weeks ago[Feature] Expose milter headers and extended symbols in legacy RSPAMC/SPAMC protocol
Vsevolod Stakhov [Sat, 21 Mar 2026 11:15:22 +0000 (11:15 +0000)] 
[Feature] Expose milter headers and extended symbols in legacy RSPAMC/SPAMC protocol

Previously, milter add/remove headers and symbol options were only
available via the JSON (HTTP) protocol. Legacy RSPAMC clients like
Exim had no way to access them through $spam_report.

This adds three new line types to the legacy text protocol output:

- X-Milter-Add: Header: value — milter headers to add (with optional
  [N] position bracket for insert-at-position)
- X-Milter-Del: Header — milter headers to remove (with optional [N]
  for specific instance removal)
- X-Symbol: Name(score); description [opt1, opt2] — extended symbol
  info with descriptions and options

Existing Symbol: lines are preserved for backward compatibility.

5 weeks ago[Minor] autolearnstats: fix false-positive learned detection 5946/head
Alexander Moisseev [Thu, 19 Mar 2026 16:42:45 +0000 (19:42 +0300)] 
[Minor] autolearnstats: fix false-positive learned detection

 rspamd_stat_check_autolearn emits error log lines sharing the
 same function prefix as its success messages. Narrow re_confirmed
 to match only success lines, which start with <MSG-ID>: autolearn.

5 weeks ago[Feature] Add rspamadm autolearnstats subcommand
Alexander Moisseev [Thu, 19 Mar 2026 15:59:30 +0000 (18:59 +0300)] 
[Feature] Add rspamadm autolearnstats subcommand

Reports Bayes autolearn events parsed from rspamd log.
Shows autolearn candidates with learning confirmation status,
sender IP, score, and per-verdict statistics.

5 weeks ago[Minor] Bump version to 4.0.0
Vsevolod Stakhov [Wed, 18 Mar 2026 21:23:29 +0000 (21:23 +0000)] 
[Minor] Bump version to 4.0.0

5 weeks ago[Fix] Weighted round-robin not respecting upstream weights across cycles
Vsevolod Stakhov [Wed, 18 Mar 2026 15:00:54 +0000 (15:00 +0000)] 
[Fix] Weighted round-robin not respecting upstream weights across cycles

When all cur_weights reached zero after one complete weighted cycle,
the code fell through to the min_checked path which selects the
least-used upstream regardless of configured weights. This caused
effectively equal distribution (1:1:1) instead of the configured
ratio (e.g. 100:100:1).

Fix: when all cur_weights are exhausted and upstreams have configured
weights, reset all cur_weights simultaneously to restart the weighted
cycle. The min_checked fallback is now only used when all original
weights are truly zero.

5 weeks agoMerge pull request #5914 from rspamd/vstakhov-stat-migrate
Vsevolod Stakhov [Wed, 18 Mar 2026 11:37:59 +0000 (11:37 +0000)] 
Merge pull request #5914 from rspamd/vstakhov-stat-migrate

[Feature] Shard migration and multi-class Bayes in statistics_dump

5 weeks agoMerge pull request #5944 from dragoangel/fix/hs-helper-properly-populate-opts
Vsevolod Stakhov [Wed, 18 Mar 2026 11:37:46 +0000 (11:37 +0000)] 
Merge pull request #5944 from dragoangel/fix/hs-helper-properly-populate-opts

[Fix] Register redis and http as known hs_helper worker options

6 weeks agoMerge pull request #5943 from dragoangel/feat/add-test-dockerfile
Vsevolod Stakhov [Tue, 17 Mar 2026 15:42:47 +0000 (15:42 +0000)] 
Merge pull request #5943 from dragoangel/feat/add-test-dockerfile

feat: add Dockerfile.test to simplify running tests locally

6 weeks agoMerge pull request #5939 from moisseev/mapstats
Vsevolod Stakhov [Tue, 17 Mar 2026 15:42:29 +0000 (15:42 +0000)] 
Merge pull request #5939 from moisseev/mapstats

[Minor] Read from STDIN when no log file is specified

6 weeks agoMerge pull request #5941 from dragoangel/feat/lupa-add-more-features
Vsevolod Stakhov [Tue, 17 Mar 2026 15:42:10 +0000 (15:42 +0000)] 
Merge pull request #5941 from dragoangel/feat/lupa-add-more-features

feat(lupa): Extends the Lupa Jinja template engine

6 weeks ago[Fix] Register redis and http as known hs_helper worker options 5944/head
Dmitriy Alekseev [Tue, 17 Mar 2026 10:43:51 +0000 (11:43 +0100)] 
[Fix] Register redis and http as known hs_helper worker options

The redis and http configuration blocks in the hs_helper worker section
were not registered via rspamd_rcl_register_worker_option, causing
rspamadm configdump to emit "unknown worker attribute: redis" warnings.
The Lua backend reads these blocks at runtime through the full UCL
options object, so they worked correctly despite not being registered.

Add proper RCL registration for both redis and http as ucl_object_t
fields so the config schema recognizes them as valid worker attributes.

Signed-off-by: Dmitriy Alekseev <1865999+dragoangel@users.noreply.github.com>
6 weeks agofeat: add Dockerfile.test to simplify running tests locally 5943/head
Dmitriy Alekseev [Mon, 16 Mar 2026 18:40:41 +0000 (19:40 +0100)] 
feat: add Dockerfile.test to simplify running tests locally

Signed-off-by: Dmitriy Alekseev <1865999+dragoangel@users.noreply.github.com>
6 weeks agofeat(lupa): fix unit tests 5941/head
Dmitriy Alekseev [Mon, 16 Mar 2026 18:20:05 +0000 (19:20 +0100)] 
feat(lupa): fix unit tests

Signed-off-by: Dmitriy Alekseev <1865999+dragoangel@users.noreply.github.com>
6 weeks agoMerge branch 'master' into feat/lupa-add-more-features
Dmitriy Alekseev [Mon, 16 Mar 2026 17:35:19 +0000 (18:35 +0100)] 
Merge branch 'master' into feat/lupa-add-more-features

6 weeks ago[Feature] Make GPT consensus thresholds configurable
Vsevolod Stakhov [Mon, 16 Mar 2026 13:07:07 +0000 (13:07 +0000)] 
[Feature] Make GPT consensus thresholds configurable

Add consensus_spam_threshold (default 0.75) and
consensus_ham_threshold (default 0.25) settings for
single-model setups that need lower thresholds.

6 weeks agoMerge branch 'master' into feat/lupa-add-more-features
Dmitriy Alekseev [Mon, 16 Mar 2026 12:32:35 +0000 (13:32 +0100)] 
Merge branch 'master' into feat/lupa-add-more-features

6 weeks agofeat(lupa): add validation filters, UCL-aware tests, and comprehensive unit tests
Dmitriy Alekseev [Mon, 16 Mar 2026 12:17:07 +0000 (13:17 +0100)] 
feat(lupa): add validation filters, UCL-aware tests, and comprehensive unit tests

New filters:
- mandatory(msg): error if nil or empty
- require_int(msg): error if not a valid integer
- require_number(msg): error if not a valid number
- require_bool(msg): error if not a UCL boolean (true/false/yes/no/on/off/1/0)
- require_duration(msg): parse duration string to seconds, error if invalid
  (supports s, ms, min, m, h, d, w, y)
- require_json(msg): error if not valid JSON/UCL
- require_size(msg): error if not a valid size (number with optional b/Kb/Mb/Gb)
- fromjson: parse JSON/UCL string into Lua table
- tobytes: convert size string to bytes (1Kb=1024, 1Mb=1048576, 1Gb=1073741824)

Modified tests to handle string inputs (env vars are always strings):
- is_number: now returns true for numeric strings like "42" or "3.14"
- is_integer: now returns true for integer strings like "42"
- is_float: now returns true for float strings like "3.14"
- is_true: now checks UCL truthy values (true/yes/on/1, case-insensitive)
- is_false: now checks UCL falsy values (false/no/off/0, case-insensitive)

New tests:
- is_json: check if value is valid JSON/UCL
- is_size: check if value is a valid size string

Added test/lua/unit/lupa.lua with 90+ test cases covering all filters,
tests, env var patterns, and real-world configuration scenarios.

Signed-off-by: Dmitriy Alekseev <1865999+dragoangel@users.noreply.github.com>
6 weeks ago[Feature] Store GPT result in mempool variable
Vsevolod Stakhov [Mon, 16 Mar 2026 12:19:23 +0000 (12:19 +0000)] 
[Feature] Store GPT result in mempool variable

Store full GPT classification result (probability, reason,
categories, model) as JSON in task mempool variable gpt_result
for use by downstream postfilter plugins.

6 weeks ago[Fix] Handle nil sel_part in GPT module, add min_words 5940/head
Vsevolod Stakhov [Mon, 16 Mar 2026 09:01:16 +0000 (09:01 +0000)] 
[Fix] Handle nil sel_part in GPT module, add min_words

- get_displayed_text_part now accepts optional min_words param
- GPT module gets sel_part separately via get_displayed_text_part
- Add min_words setting (default 10) to scan short messages
- Guard redis_cache_key, insert_results and check_llm_cached
  against nil sel_part to prevent crashes

6 weeks agoMerge pull request #5938 from rspamd/vstakhov-lupa-enhancements
Vsevolod Stakhov [Sun, 15 Mar 2026 16:42:33 +0000 (16:42 +0000)] 
Merge pull request #5938 from rspamd/vstakhov-lupa-enhancements

[Feature] Add missing Jinja2 filters and tests to Lupa

6 weeks ago[Minor] Read from STDIN when no log file is specified 5939/head
Alexander Moisseev [Sun, 15 Mar 2026 12:52:01 +0000 (15:52 +0300)] 
[Minor] Read from STDIN when no log file is specified

6 weeks ago[Fix] Add PCRE2 complexity checks before JIT compilation
Vsevolod Stakhov [Sun, 15 Mar 2026 12:26:17 +0000 (12:26 +0000)] 
[Fix] Add PCRE2 complexity checks before JIT compilation

Check compiled pattern size, frame size, and capture count
before calling pcre2_jit_compile to avoid crashes on
pathological patterns. Also set map->map pointer consistently
in lua_config_add_map for all map types.

6 weeks ago[Fix] Fix build with ENABLE_HYPERSCAN=OFF
Vsevolod Stakhov [Sun, 15 Mar 2026 11:48:13 +0000 (11:48 +0000)] 
[Fix] Fix build with ENABLE_HYPERSCAN=OFF

Unset WITH_HYPERSCAN cache variable when hyperscan is disabled,
and guard hs_magic usage in re_cache with WITH_HYPERSCAN ifdef.

6 weeks ago[Fix] Remove unsupported Delta codec from ClickHouse UUID column
Vsevolod Stakhov [Sun, 15 Mar 2026 10:55:31 +0000 (10:55 +0000)] 
[Fix] Remove unsupported Delta codec from ClickHouse UUID column

ClickHouse does not support Delta compression for UUID type (16 bytes),
as Delta codec only works with 1/2/4/8 byte data types.

6 weeks ago[Feature] Add missing Jinja2 filters and tests to Lupa template engine 5938/head
Vsevolod Stakhov [Sun, 15 Mar 2026 10:10:19 +0000 (10:10 +0000)] 
[Feature] Add missing Jinja2 filters and tests to Lupa template engine

Add commonly needed Jinja2 filters: split, trim, tojson, unique, min,
max, items, keys, values, wordwrap. Add tests: is_in, is_startswith,
is_endswith, is_match, is_boolean, is_true, is_false, is_integer,
is_float, and comparison tests (is_eq, is_ne, is_lt, is_le, is_gt,
is_ge).

6 weeks ago[Fix] Fix Clickhouse column name mismatch: UUID -> TaskUUID
Vsevolod Stakhov [Sat, 14 Mar 2026 22:22:28 +0000 (22:22 +0000)] 
[Fix] Fix Clickhouse column name mismatch: UUID -> TaskUUID

The insert field list used 'UUID' but the actual column is named
'TaskUUID' (as defined in schema and migration 9), causing
NO_SUCH_COLUMN_IN_TABLE errors on insert.

6 weeks ago[Feature] Add context_augment hook to GPT module
Vsevolod Stakhov [Sat, 14 Mar 2026 22:13:42 +0000 (22:13 +0000)] 
[Feature] Add context_augment hook to GPT module

Add a new `context_augment` configuration option that accepts Lua code
returning an async function(task, content, callback).  The callback
receives a string that gets injected as additional context into the
LLM prompt alongside existing user/domain and search contexts.

This enables external Lua code to enrich LLM requests with arbitrary
context — e.g., Telegram channel topic and recent messages for
community spam detection.

The augment function runs in parallel with other context fetchers
and supports async operations (Redis, HTTP).

6 weeks ago[Fix] Fix rspamc neural_learn config fetch and output
Vsevolod Stakhov [Sat, 14 Mar 2026 20:31:15 +0000 (20:31 +0000)] 
[Fix] Fix rspamc neural_learn config fetch and output

- Fix config fetch port: when user specifies the default scan port
  (11333), redirect the /plugins/neural/config preflight request to
  the controller port (11334) where the endpoint actually lives.
  Previously, the config fetch used the user-specified port verbatim,
  causing "invalid command" errors on the normal worker.

- Fix misleading output: rspamc_neural_learn_output no longer defaults
  to "success = true" when the response lacks an explicit success field.
  For scan-based learning (checkv2 path), it now detects the scan
  response and shows method = "scan".  For missing/error responses,
  it correctly reports success = false.

- Add user-visible note when the config fetch fails, explaining the
  fallback to scan-based learning.

6 weeks agoMerge pull request #5937 from dragoangel/allow-template-maps-mirror
Vsevolod Stakhov [Sat, 14 Mar 2026 20:19:19 +0000 (20:19 +0000)] 
Merge pull request #5937 from dragoangel/allow-template-maps-mirror

feat: allow utilize own rspamd mirror via env variable

6 weeks agoMerge branch 'master' into allow-template-maps-mirror 5937/head
Dmitriy Alekseev [Sat, 14 Mar 2026 19:44:48 +0000 (20:44 +0100)] 
Merge branch 'master' into allow-template-maps-mirror

6 weeks agofeat: allow utilize own rspamd mirror via env variable
Dmitriy Alekseev [Sat, 14 Mar 2026 19:44:00 +0000 (20:44 +0100)] 
feat: allow utilize own rspamd mirror via env variable

Signed-off-by: Dmitriy Alekseev <1865999+dragoangel@users.noreply.github.com>
6 weeks agoMerge pull request #5935 from rspamd/vstakhov-http-caseless-lua
Vsevolod Stakhov [Fri, 13 Mar 2026 14:17:15 +0000 (14:17 +0000)] 
Merge pull request #5935 from rspamd/vstakhov-http-caseless-lua

[Feature] Add case-insensitive table type for HTTP headers

6 weeks ago[Minor] Fix copyright year to 2026 5935/head
Vsevolod Stakhov [Fri, 13 Mar 2026 14:15:00 +0000 (14:15 +0000)] 
[Minor] Fix copyright year to 2026

6 weeks ago[Test] Add unit tests for caseless table
Vsevolod Stakhov [Fri, 13 Mar 2026 13:58:33 +0000 (13:58 +0000)] 
[Test] Add unit tests for caseless table

25 tests covering creation, case-insensitive lookup, key case
preservation, assignment, deletion, has_key, iteration via each(),
to_table conversion, multi-value get_all, and edge cases including
long keys, empty keys, and metamethod isolation.

6 weeks ago[Feature] Add case-insensitive table type for HTTP headers
Vsevolod Stakhov [Fri, 13 Mar 2026 13:54:35 +0000 (13:54 +0000)] 
[Feature] Add case-insensitive table type for HTTP headers

Introduce rspamd{caseless_table} userdata type that provides
case-insensitive key lookup while preserving original key case.
HTTP response headers now use this type instead of plain Lua tables,
fixing two issues: headers were forcibly lowercased (mutating original
data) and duplicate headers were silently lost.

Multi-value headers are stored as arrays and can be retrieved via
get_all(key). The __index metamethod returns the first value for
convenience. The type is generic and reusable beyond HTTP.

6 weeks ago[Minor] Improve restore logging and add incremental GC 5914/head
Vsevolod Stakhov [Fri, 13 Mar 2026 12:20:09 +0000 (12:20 +0000)] 
[Minor] Improve restore logging and add incremental GC

Add progress reporting every 10 seconds with throughput rate and
Lua memory usage. Run incremental GC after each batch flush and
full GC between files to avoid memory spikes on large restores.

6 weeks agoMerge pull request #5931 from rob4226/fix-dmarc-help
Vsevolod Stakhov [Thu, 12 Mar 2026 20:16:27 +0000 (20:16 +0000)] 
Merge pull request #5931 from rob4226/fix-dmarc-help

[Minor] Fix default date description in rspamadm dmarc_report help

6 weeks agoMerge branch 'master' into vstakhov-stat-migrate
Vsevolod Stakhov [Thu, 12 Mar 2026 12:22:31 +0000 (12:22 +0000)] 
Merge branch 'master' into vstakhov-stat-migrate

6 weeks ago[Fix] Add reconnection with retry logic for statistics restore
Vsevolod Stakhov [Thu, 12 Mar 2026 12:20:31 +0000 (12:20 +0000)] 
[Fix] Add reconnection with retry logic for statistics restore

When restoring large datasets (24M+ lines), Redis connections can get
terminated mid-restore. Add retry logic with automatic reconnection
that resumes from the failed pipeline chunk, avoiding HINCRBYFLOAT
double-counting by skipping past ambiguously-applied chunks.

6 weeks agoMerge pull request #5924 from rspamd/vstakhov-neural-sharing
Vsevolod Stakhov [Wed, 11 Mar 2026 13:21:54 +0000 (13:21 +0000)] 
Merge pull request #5924 from rspamd/vstakhov-neural-sharing

[Feature] Add external pretrained neural model support

7 weeks agoMerge branch 'master' into vstakhov-neural-sharing 5924/head
Vsevolod Stakhov [Tue, 10 Mar 2026 17:37:28 +0000 (17:37 +0000)] 
Merge branch 'master' into vstakhov-neural-sharing

7 weeks ago[Fix] Fix external neural model merge defects
Vsevolod Stakhov [Tue, 10 Mar 2026 17:35:51 +0000 (17:35 +0000)] 
[Fix] Fix external neural model merge defects

- merge_weights returns boolean, not ANN object: use ext_ann directly
- Add missing digest/symbols/distance fields for external-only set.ann
- Fix inverted alpha in merge call (alpha meant external weight, not local)
- Add missing newline at EOF in lua_kann.c

7 weeks ago[Fix] Fix fuzzy TCP frame buffer overflow for encrypted v2 replies
Vsevolod Stakhov [Tue, 10 Mar 2026 12:57:09 +0000 (12:57 +0000)] 
[Fix] Fix fuzzy TCP frame buffer overflow for encrypted v2 replies

The rspamd_fuzzy_tcp_frame payload was sized for v1 encrypted replies
(136 bytes) but v2 encrypted replies are 184 bytes, causing a buffer
overflow when sending multi-flag responses over TCP with encryption.
Use a union to accommodate both v1 and v2 reply sizes.

Add multi-flag delete tests for all TCP transport modes.

7 weeks ago[Fix] Raise fasttext dictionary token limit
Vsevolod Stakhov [Tue, 10 Mar 2026 11:41:49 +0000 (11:41 +0000)] 
[Fix] Raise fasttext dictionary token limit

Allow valid fasttext models with long dictionary entries to load without tripping the shim safety cap. Fixes #5919.

7 weeks ago[Minor] Fix default date description in rspamadm dmarc_report help 5931/head
Rob4226 [Tue, 10 Mar 2026 09:04:36 +0000 (05:04 -0400)] 
[Minor] Fix default date description in rspamadm dmarc_report help

Change the help text for the `date` argument of `rspamadm dmarc_report`
from "today" to "yesterday". When the command is run without specifying
a date, it actually processes reports for yesterday, so this update
makes the help message match the command's behavior.

7 weeks agoMerge pull request #5923 from Jesssullivan/dev/dkim-sign-headers-segfault
Vsevolod Stakhov [Mon, 9 Mar 2026 12:57:09 +0000 (12:57 +0000)] 
Merge pull request #5923 from Jesssullivan/dev/dkim-sign-headers-segfault

[Feature] Prevent SIGSEGV when sign_headers is not a string

7 weeks ago[Fix] Accept fuzzy TCP v2 reply frames
Vsevolod Stakhov [Mon, 9 Mar 2026 12:50:18 +0000 (12:50 +0000)] 
[Fix] Accept fuzzy TCP v2 reply frames

Allow TCP fuzzy replies to use v2 frame sizes so valid 144-byte responses are not rejected as invalid frame lengths. Fixes #5930.

7 weeks ago[Fix] Prevent SIGSEGV when sign_headers is not a string 5923/head
Jess Sullivan [Thu, 5 Mar 2026 17:42:18 +0000 (12:42 -0500)] 
[Fix] Prevent SIGSEGV when sign_headers is not a string

Add NULL guard in rspamd_create_dkim_sign_context() before strlen(headers)
to return a proper GError instead of crashing when headers is NULL.

Add type validation at config load time for sign_headers in dkim_signing,
dkim, and arc modules — rejects non-string types with a clear error message.

Fixes: SIGSEGV in dkim.c when sign_headers is configured as a UCL array
(ucl_object_tostring returns NULL for arrays, which hits strlen).

-jess

7 weeks agoMerge pull request #5929 from moisseev/test
Vsevolod Stakhov [Sun, 8 Mar 2026 22:11:22 +0000 (22:11 +0000)] 
Merge pull request #5929 from moisseev/test

[Test] Skip scheduled integration tests in forks

7 weeks agoMerge pull request #5927 from moisseev/replies
Vsevolod Stakhov [Sun, 8 Mar 2026 22:11:04 +0000 (22:11 +0000)] 
Merge pull request #5927 from moisseev/replies

[Fix] Skip recipient check when no hash found in Redis

7 weeks agoMerge pull request #5928 from moisseev/droid-review
Vsevolod Stakhov [Sun, 8 Mar 2026 22:10:49 +0000 (22:10 +0000)] 
Merge pull request #5928 from moisseev/droid-review

[Test] Restrict droid review to upstream repository

7 weeks ago[Test] Skip scheduled integration tests in forks 5929/head
Alexander Moisseev [Sun, 8 Mar 2026 12:39:26 +0000 (15:39 +0300)] 
[Test] Skip scheduled integration tests in forks

Limit scheduled integration-test runs to rspamd/rspamd while keeping
manual start available in forks. This avoids unnecessary fork cron
runs and reduces noisy CI failures unrelated to upstream.

7 weeks ago[Test] Restrict droid review to upstream repository 5928/head
Alexander Moisseev [Sun, 8 Mar 2026 10:54:03 +0000 (13:54 +0300)] 
[Test] Restrict droid review to upstream repository

7 weeks ago[Fix] Skip recipient check when no hash found in Redis 5927/head
Alexander Moisseev [Sat, 7 Mar 2026 11:46:45 +0000 (14:46 +0300)] 
[Fix] Skip recipient check when no hash found in Redis

When a key is not found in Redis, lua_redis returns a redis.null
userdata (not nil), which is truthy and caused check_recipient()
to be called unconditionally, logging a misleading "no recipients
are matching hash" message despite no hash being stored.

7 weeks agoMerge branch 'master' into vstakhov-stat-migrate
Vsevolod Stakhov [Sat, 7 Mar 2026 09:51:57 +0000 (09:51 +0000)] 
Merge branch 'master' into vstakhov-stat-migrate

7 weeks agoMerge branch 'master' into vstakhov-neural-sharing
Vsevolod Stakhov [Sat, 7 Mar 2026 09:51:08 +0000 (09:51 +0000)] 
Merge branch 'master' into vstakhov-neural-sharing

7 weeks ago[Minor] Fix model name
Vsevolod Stakhov [Sat, 7 Mar 2026 09:50:53 +0000 (09:50 +0000)] 
[Minor] Fix model name

7 weeks agoMerge branch 'master' into vstakhov-neural-sharing
Vsevolod Stakhov [Sat, 7 Mar 2026 09:44:14 +0000 (09:44 +0000)] 
Merge branch 'master' into vstakhov-neural-sharing

7 weeks ago[Fix] Upgrade legacy cached maps to aligned format
Vsevolod Stakhov [Fri, 6 Mar 2026 18:48:53 +0000 (18:48 +0000)] 
[Fix] Upgrade legacy cached maps to aligned format

7 weeks ago[Fix] Revert invalid map cache seek workaround
Vsevolod Stakhov [Fri, 6 Mar 2026 18:46:37 +0000 (18:46 +0000)] 
[Fix] Revert invalid map cache seek workaround

7 weeks ago[Fix] Rewrite map cache headers from file start
Vsevolod Stakhov [Fri, 6 Mar 2026 18:03:01 +0000 (18:03 +0000)] 
[Fix] Rewrite map cache headers from file start

7 weeks ago[Minor] droid-code-review: switch model to gpt5.4, rewrite prompt for precision ...
Copilot [Fri, 6 Mar 2026 17:08:20 +0000 (17:08 +0000)] 
[Minor] droid-code-review: switch model to gpt5.4, rewrite prompt for precision (#5925)

7 weeks ago[Fix] Handle stale neural export profiles
Vsevolod Stakhov [Fri, 6 Mar 2026 17:06:49 +0000 (17:06 +0000)] 
[Fix] Handle stale neural export profiles

7 weeks agoMerge pull request #5922 from moisseev/replies
Vsevolod Stakhov [Fri, 6 Mar 2026 11:48:06 +0000 (11:48 +0000)] 
Merge pull request #5922 from moisseev/replies

[Minor] Skip empty In-Reply-To header in replies check

7 weeks ago[Feature] Add external pretrained neural model support
Vsevolod Stakhov [Fri, 6 Mar 2026 10:49:43 +0000 (10:49 +0000)] 
[Feature] Add external pretrained neural model support

This commit adds the ability to load pretrained neural network models
from external sources (HTTP/HTTPS) and merge them with locally trained
weights. Users can receive a pretrained model and fine-tune it with
their own data.

Model format (msgpack with magic "RNM1"):
- magic: format identifier
- version: format version (currently 1)
- model_version: model training version
- providers_digest: must match local providers config
- ann_data: serialized KANN (zstd compressed)
- pca_data: optional PCA matrix
- norm_stats, roc_thresholds: optional metadata

Key changes:
- lualib/lua_neural_external.lua: new module for external model handling
  - Model parsing, KANN loading, weight merging via interpolation
  - Map-based loading with signature verification support
  - Base model storage in Redis for future re-merge

- contrib/kann/kann.c: add kann_merge_weights() for weight interpolation
  - w_new = alpha * w_external + (1-alpha) * w_local
  - kann_is_compatible() for architecture compatibility check

- src/lua/lua_kann.c: Lua bindings for merge_weights and is_compatible

- Neural plugin integration:
  - Register external model as callback map at config time
  - Apply loaded model to all settings elements
  - Automatic update checking via map infrastructure

Configuration example:
  neural {
    rules {
      spam_filter = {
        external_model = {
          url = "https://your-provider.com/models/<digest>";
          sign_key = "your_key";
          merge_alpha = 0.6;  # 60% external, 40% local
        };
      };
    };
  }

7 weeks ago[Fix] Preserve content flags for injected query URLs
Vsevolod Stakhov [Fri, 6 Mar 2026 10:00:32 +0000 (10:00 +0000)] 
[Fix] Preserve content flags for injected query URLs

Propagate the parent URL flags when task:inject_url() extracts nested query URLs. This keeps the content flag on URLs injected from computed parts such as PDF text, so follow-up query URLs are classified the same way as the outer injected URL.

7 weeks ago[Fix] Preserve duplicate URLs across MIME parts
Vsevolod Stakhov [Fri, 6 Mar 2026 08:44:21 +0000 (08:44 +0000)] 
[Fix] Preserve duplicate URLs across MIME parts

Do not suppress URLs from mime_part:get_urls() when the same URL was already seen in another MIME part. This restores per-part URL visibility for multipart/alternative messages and keeps text/plain URLs available even when text/html contains the same links.

7 weeks ago[Fix] Speed up shard migration and harden restore batching
Vsevolod Stakhov [Thu, 5 Mar 2026 22:38:26 +0000 (22:38 +0000)] 
[Fix] Speed up shard migration and harden restore batching

7 weeks agoMerge pull request #5921 from rspamd/vstakhov-follow-master-mirror
Vsevolod Stakhov [Thu, 5 Mar 2026 21:03:52 +0000 (21:03 +0000)] 
Merge pull request #5921 from rspamd/vstakhov-follow-master-mirror

[Feature] Add follow_master option for proxy mirrors

7 weeks ago[Minor] Skip empty In-Reply-To header in replies check 5922/head
Alexander Moisseev [Thu, 5 Mar 2026 17:09:40 +0000 (20:09 +0300)] 
[Minor] Skip empty In-Reply-To header in replies check

An empty `In-Reply-To` header value ("") is truthy in Lua,
bypassing the `nil` check. In `replies_check` this caused a
misleading log entry "ignoring reply to  as no recipients
are matching hash ". In `replies_check_cookie` it triggered
an unnecessary `decrypt_cookie` call.

7 weeks ago[Fix] Fix restore stack overflow, migrate memory and speed
Vsevolod Stakhov [Thu, 5 Mar 2026 10:36:12 +0000 (10:36 +0000)] 
[Fix] Fix restore stack overflow, migrate memory and speed

Restore: chunk redis pipeline into batches of 1000 commands per
exec() call to prevent Lua stack overflow on large dump files.

Dump: chunk HGETALL pipeline the same way.

Migrate: replace EVAL scripts with direct pipelined commands.
Collect all misplaced prefixes upfront, then process each with
pipelined HGETALL/HMSET/DEL. Explicit collectgarbage() every
100 prefixes to prevent memory bloat.

Restore: periodic GC and progress logging every 10 batches.

7 weeks ago[Feature] Add follow_master option for proxy mirror connections 5921/head
Vsevolod Stakhov [Wed, 4 Mar 2026 11:10:18 +0000 (11:10 +0000)] 
[Feature] Add follow_master option for proxy mirror connections

When a mirror has a short timeout to avoid delays from misconfigured
mirrors, the mirror connection gets prematurely terminated if the
upstream takes longer than the mirror timeout. The new follow_master
option ties the mirror's lifetime to the master upstream: the mirror
stays alive while the upstream is processing and is terminated once the
upstream completes or permanently errors out.

8 weeks ago[Fix] Move --classifier to top-level parser
Vsevolod Stakhov [Tue, 3 Mar 2026 10:11:07 +0000 (10:11 +0000)] 
[Fix] Move --classifier to top-level parser

The --classifier option must be available for all subcommands
(dump, restore, migrate), not just dump and migrate. Move it
to the top-level parser and use select_classifier in restore
handler as well.

8 weeks agoMerge pull request #5917 from moisseev/playwright
Vsevolod Stakhov [Sun, 1 Mar 2026 17:54:55 +0000 (17:54 +0000)] 
Merge pull request #5917 from moisseev/playwright

[Test] Use Node.js 22 for legacy Playwright 1.45.3 job

8 weeks ago[Test] Use Node.js 22 for legacy Playwright 1.45.3 job 5917/head
Alexander Moisseev [Sun, 1 Mar 2026 14:14:50 +0000 (17:14 +0300)] 
[Test] Use Node.js 22 for legacy Playwright 1.45.3 job

Playwright 1.45.3 predates Node.js 24 support (added in v1.55),
causing an immediate crash on startup. Use Node.js 22 for the
legacy matrix entry.

8 weeks agoMerge pull request #5916 from moisseev/dev-dependencies
Vsevolod Stakhov [Sat, 28 Feb 2026 09:33:18 +0000 (09:33 +0000)] 
Merge pull request #5916 from moisseev/dev-dependencies

[Test] Update dev dependencies

8 weeks ago[Test] Update dev dependencies 5916/head
Alexander Moisseev [Sat, 28 Feb 2026 06:29:07 +0000 (09:29 +0300)] 
[Test] Update dev dependencies

- Update ESLint to v10, stylelint to v17, and related packages
- Bump Node.js to v24 LTS in CI

Closes #5915

8 weeks ago[Fix] Require classifier selection for multi-classifier configs
Vsevolod Stakhov [Fri, 27 Feb 2026 15:33:45 +0000 (15:33 +0000)] 
[Fix] Require classifier selection for multi-classifier configs

When multiple bayes classifiers are configured, dump and migrate now
require --classifier to select which one to operate on. With a single
classifier the flag is optional.

Also fix the SCAN pattern for token keys: use `<prefix>_*` instead of
`<prefix>*_*` to avoid matching tokens from unrelated prefixes.

8 weeks ago[Feature] Add shard migration and multi-class support to statistics_dump
Vsevolod Stakhov [Fri, 27 Feb 2026 14:25:25 +0000 (14:25 +0000)] 
[Feature] Add shard migration and multi-class support to statistics_dump

Add `rspamadm statistics_dump migrate` subcommand for migrating per-user
Bayes data between Redis shards after the Jump Hash to Ketama transition.
The tool scans all shards, identifies misplaced prefixes via
get_upstream_by_hash, and moves them in batches using Redis Lua scripts.

Also fix multi-class Bayes support: dump/restore now handles arbitrary
statfile classes (not just binary spam/ham) by collecting all symbols
from classifier config with proper class label mapping. The dump command
now iterates all shards via all_upstreams() for complete data export.

8 weeks ago[Fix] Force recompilation of stale hyperscan classes instead of skipping
Vsevolod Stakhov [Fri, 27 Feb 2026 11:15:36 +0000 (11:15 +0000)] 
[Fix] Force recompilation of stale hyperscan classes instead of skipping

When a cached hyperscan blob fails validation during load (stale IDs
pointing to wrong re_class), mark the class with needs_recompile flag.
On subsequent exists_async check in hs_helper, ignore the "exists"
result and proceed with recompilation instead of skipping.

8 weeks ago[Fix] Do not enable HS cleanup when disable_hyperscan is set
Vsevolod Stakhov [Fri, 27 Feb 2026 11:01:13 +0000 (11:01 +0000)] 
[Fix] Do not enable HS cleanup when disable_hyperscan is set

When disable_hyperscan is true, workers skip loading hyperscan databases
and never notify main about known cache files. This caused main to delete
all cached .hs.zst files on exit since none were marked as "known".
Also promote worker hyperscan notification to info log level.

8 weeks ago[Fix] Include HS magic in cache key hashes to force recompilation on version bump
Vsevolod Stakhov [Fri, 27 Feb 2026 10:42:20 +0000 (10:42 +0000)] 
[Fix] Include HS magic in cache key hashes to force recompilation on version bump

8 weeks ago[Feature] Per-class deterministic regexp IDs in re_cache
Vsevolod Stakhov [Fri, 27 Feb 2026 10:22:18 +0000 (10:22 +0000)] 
[Feature] Per-class deterministic regexp IDs in re_cache

Group regexp IDs by class instead of assigning them globally.
Each class gets a deterministic base_offset in the global array,
and hyperscan stores intra-class IDs (0..M-1). This prevents
adding/removing a regexp in one class from shifting IDs in all
other classes, eliminating stale hyperscan databases and
unnecessary recompilations.

Key changes:
- Sort classes by class_id, regexps within each class by content hash
- Assign contiguous global IDs per class (base_offset + local_index)
- Use class-local regexp count in per-class hash (not global count)
- Hyperscan compile stores intra-class IDs, callback translates back
- Bump blob magic version to reject old format databases

2 months agoMerge pull request #5909 from rspamd/vstakhov-fasttext-maps
Vsevolod Stakhov [Thu, 26 Feb 2026 13:13:02 +0000 (13:13 +0000)] 
Merge pull request #5909 from rspamd/vstakhov-fasttext-maps

[Feature] Fasttext models via maps infrastructure

2 months ago[Feature] Wire Lua rspamd_fasttext through maps infrastructure 5909/head
Vsevolod Stakhov [Thu, 26 Feb 2026 12:54:05 +0000 (12:54 +0000)] 
[Feature] Wire Lua rspamd_fasttext through maps infrastructure

Add load_map(cfg, path) to rspamd_fasttext module that loads FastText
models via the maps infrastructure (HTTP URLs + file with shared mmap).
The fasttext_embed neural provider now registers models as maps at
config time via a new init callback, enabling shared memory across
workers and automatic reload on map updates.

2 months ago[Fix] Fix SIGSEGV on termination in fasttext map dtor callback
Vsevolod Stakhov [Wed, 25 Feb 2026 15:26:58 +0000 (15:26 +0000)] 
[Fix] Fix SIGSEGV on termination in fasttext map dtor callback

Two bugs in the map callback lifecycle caused a crash during
rspamd_map_remove_all at shutdown:

1. Type mismatch: fin_callback published *target = model pointer
   (fasttext_model*), but the dtor cast it to fasttext_map_data* -
   the standard map pattern requires *target = data->cur_data.

2. Use-after-free: map->user_data pointed into the fasttext_langdet
   object which was destroyed before rspamd_map_remove_all ran.

Fix by allocating the user_data target on cfg->cfg_pool (outlives
the lang detector), following the standard map consumer pattern,
and accessing the model through a get_model() indirection.

2 months ago[Fix] Use 16K map cache header for mmap alignment on ARM64
Vsevolod Stakhov [Wed, 25 Feb 2026 14:59:53 +0000 (14:59 +0000)] 
[Fix] Use 16K map cache header for mmap alignment on ARM64

Apple Silicon requires mmap offsets to be 16K-aligned (page size is
16384, not 4096). Bump RSPAMD_MAP_CACHE_HEADER_SIZE to 16384 to work
on all common architectures.

2 months ago[Feature] Wire fasttext lang detector through maps infrastructure
Vsevolod Stakhov [Wed, 25 Feb 2026 14:51:07 +0000 (14:51 +0000)] 
[Feature] Wire fasttext lang detector through maps infrastructure

The fasttext language detector now supports HTTP/HTTPS URLs for model
loading via the maps system, enabling automatic download, disk caching,
periodic reload, and cross-worker mmap sharing.

Changes:
- fasttext_model::load() accepts an offset parameter for mmap at a
  non-zero position (used with page-aligned map cache files)
- fasttext_langdet uses rspamd_map_is_map() to detect URLs vs local
  paths; URLs go through rspamd_map_add() with RSPAMD_MAP_FILE_NO_READ
- Map callbacks (read/fin/dtor) handle atomic model swap on reload
- Local file paths continue to work as before with direct loading

2 months ago[Feature] Page-aligned map cache header for no_file_read mmap support
Vsevolod Stakhov [Wed, 25 Feb 2026 12:57:35 +0000 (12:57 +0000)] 
[Feature] Page-aligned map cache header for no_file_read mmap support

Upgrade HTTP map cache file format to use a page-aligned (4096 byte)
header so that no_file_read consumers (CDB, fasttext models) can mmap
the cached file directly at a fixed offset without needing a separate
sidecar file.

Changes:
- Bump cache magic to rmcd2001; old rmcd2000 files are read gracefully
  and rewritten on next update
- Header page (4096 bytes) contains struct + etag + zero padding; data
  payload always starts at RSPAMD_MAP_CACHE_HEADER_SIZE offset
- For no_file_read maps with HTTP backends, pass the cache file path
  to read_callback (instead of payload bytes) with no_file_read_offset
  set to 4096; for file backends offset remains 0
- Add rspamd_map_get_no_file_read_offset() public API for consumers
- Refactor cache path computation into rspamd_map_cache_file_path()
  helper, removing 4 duplicate hash+snprintf blocks
- Handle all 3 HTTP data delivery paths: live GET (controller),
  SHM cache read (scanner workers), disk cache preload (startup)