]> git.ipfire.org Git - thirdparty/rspamd.git/log
thirdparty/rspamd.git
7 weeks ago[Fix] Refine structural alternative check to leaf text/* parts
Vsevolod Stakhov [Thu, 19 Feb 2026 10:58:41 +0000 (10:58 +0000)] 
[Fix] Refine structural alternative check to leaf text/* parts

The previous check counted any sibling in multipart/alternative,
but multipart/related with only images or malformed empty related
parts are not real alternatives. Now only leaf text/* non-html
siblings count (e.g. text/calendar, text/enriched).

7 weeks ago[Fix] Check MIME structure for alternatives in has_only_html_part
Vsevolod Stakhov [Thu, 19 Feb 2026 10:31:07 +0000 (10:31 +0000)] 
[Fix] Check MIME structure for alternatives in has_only_html_part

has_only_html_part() relied solely on alt_text_part to find alternatives,
but parts like text/calendar (detected as ics with no_text=true) are not
in text_parts and thus invisible to the search. Now we also walk the MIME
tree: if the HTML part sits inside a multipart/alternative with other
siblings, it has a structural alternative and MIME_HTML_ONLY should not
fire.

7 weeks ago[Fix] Fix XML detection overriding HTML in content type detection
Vsevolod Stakhov [Wed, 18 Feb 2026 19:01:23 +0000 (19:01 +0000)] 
[Fix] Fix XML detection overriding HTML in content type detection

HTML parts containing an embedded <?xml?> prolog (e.g. inside the body)
were misdetected as application/xml. Since xml type has no_text=true,
this excluded the HTML part from text_parts entirely, causing
has_only_html_part() to return false and MIME_HTML_ONLY to not fire.

- Remove xml binary pattern from patterns.lua (it preempted the text
  heuristic which correctly prioritises HTML)
- Guard xml text pattern so it cannot override HTML when HTML markers
  are also present
- Raise xml text pattern weight to 40 to preserve pure XML detection

7 weeks ago[Fix] Filter forbidden_ids from multi-flag extra flags in v2 reply
Vsevolod Stakhov [Wed, 18 Feb 2026 15:33:02 +0000 (15:33 +0000)] 
[Fix] Filter forbidden_ids from multi-flag extra flags in v2 reply

Extract forbidden flag checks into rspamd_fuzzy_filter_forbidden_v2()
which filters both primary and extra flags. If primary is forbidden
but valid extras remain, promotes first valid extra to primary.

7 weeks ago[Test] Update fuzzy tests for multi-flag support
Vsevolod Stakhov [Wed, 18 Feb 2026 12:09:47 +0000 (12:09 +0000)] 
[Test] Update fuzzy tests for multi-flag support

Rename Overwrite tests to Multi Flag tests since multiple flags
now coexist instead of overwriting. Add Multi Flag Delete test.

7 weeks ago[Feature] Add multi-flag fuzzy hash support with Lua-based Redis update path
Vsevolod Stakhov [Wed, 18 Feb 2026 11:23:31 +0000 (11:23 +0000)] 
[Feature] Add multi-flag fuzzy hash support with Lua-based Redis update path

Support up to 8 flag slots per fuzzy hash (primary + 7 extra), enabling
multiple rules to match against the same digest with independent flag/value
pairs. The highest-value flag is always promoted to the primary slot for
backward compatibility.

The Redis update path (ADD/DEL/REFRESH) is moved from a C MULTI/EXEC
pipeline with an embedded EVAL string to a proper Lua architecture
following the Bayes pattern: a Redis script in lualib/redis_scripts/
loaded via lua_redis.load_redis_script_from_file(), with a Lua module
(lua_fuzzy_redis.lua) providing an async update functor called from C
via lua_pcall. This gives automatic EVALSHA + NOSCRIPT recovery and
keeps the multi-flag merge logic in a maintainable .lua file.

Wire protocol extended with epoch 12 (RSPAMD_FUZZY_EPOCH12) carrying
rspamd_fuzzy_reply_v2 with n_extra_flags and up to 7 extra flag entries.

7 weeks ago[Fix] Distinguish explicit multi-class from legacy binary configs
Alexander Moisseev [Tue, 17 Feb 2026 13:13:48 +0000 (16:13 +0300)] 
[Fix] Distinguish explicit multi-class from legacy binary configs

Check is_spam_converted flag to differentiate between:
- Explicit class declaration (new format) -> multi-class
- Converted is_spam=true/false (legacy) -> binary

This fixes incorrect "binary" detection for explicit multi-class
configurations using class="spam" and class="ham".

7 weeks ago[Fix] Fix JPEG dimension parsing - use 256 instead of 0xff
Vsevolod Stakhov [Tue, 17 Feb 2026 10:29:17 +0000 (10:29 +0000)] 
[Fix] Fix JPEG dimension parsing - use 256 instead of 0xff

7 weeks ago[Fix] Fix JSON emission for implicit arrays in libucl
Vsevolod Stakhov [Mon, 16 Feb 2026 19:08:55 +0000 (19:08 +0000)] 
[Fix] Fix JSON emission for implicit arrays in libucl

When emitting UCL objects with implicit arrays (multiple values for the
same key) as JSON, the emitter was producing invalid output by:
- Not printing the key before the array for non-first elements
- Missing comma separators between elements

This caused rspamadm configdump -j to output malformed JSON like:
  "actions": {...}[
instead of:
  "actions": {...},
  "group": [

7 weeks ago[Feature] WebUI: Add classifier metadata to Bayes statistics table
Alexander Moisseev [Mon, 16 Feb 2026 18:34:29 +0000 (21:34 +0300)] 
[Feature] WebUI: Add classifier metadata to Bayes statistics table

- Display `classifier name` with type badges (`multi-class`, `per-user`)
and `class` field for each statfile with fallback for old server responses
- Group statfiles by classifier name with rowspan (similar to server grouping)
- Update hover handler to support nested rowspan cells
- Highlight all parent rowspan cells when hovering classifier or statfile

7 weeks ago[Feature] Extend /stat endpoint with classifier metadata
Alexander Moisseev [Mon, 16 Feb 2026 08:04:20 +0000 (11:04 +0300)] 
[Feature] Extend /stat endpoint with classifier metadata

Add classifier object (name, type, per_user) and class field to each
statfile in /stat response.

7 weeks ago[Minor] Fix compile warnings
Vsevolod Stakhov [Mon, 16 Feb 2026 16:00:52 +0000 (16:00 +0000)] 
[Minor] Fix compile warnings

- Fix hexdigests array size (use empty brackets for compiler to determine)
- Fix char8_t to char32_t implicit conversion in replxx terminal
- Fix hex format specifier in hyperscan debug logging (%xd not %x)
- Add forward declaration for struct rspamd_external_libs_ctx
- Remove unused is_msgpack variable in protocol.c
- Fix logic bug: c >= 'a' || c <= 'f' should be && in hex parsing

7 weeks ago[Fix] Catch all exceptions when loading fasttext model to avoid crash
Vsevolod Stakhov [Mon, 16 Feb 2026 15:36:19 +0000 (15:36 +0000)] 
[Fix] Catch all exceptions when loading fasttext model to avoid crash

When the fasttext language detection model file doesn't exist or is
corrupted, fasttext library throws an exception. Add a catch-all handler
to prevent crashes when the model path is invalid or the file is missing.

Also improved error messages to include the model path for debugging.

7 weeks ago[Minor] Backport ucl_object_iterate_end() from libucl to fix iterator leak
Vsevolod Stakhov [Mon, 16 Feb 2026 15:36:16 +0000 (15:36 +0000)] 
[Minor] Backport ucl_object_iterate_end() from libucl to fix iterator leak

Add ucl_object_iterate_end() function to free resources associated with
an inline iterator when iteration is abandoned before completion. This
fixes a potential memory leak when iterating over UCL_OBJECT types where
internal heap state is allocated.

Changes backported from libucl 0.9.3:
- Add ucl_hash_iterate_free() to ucl_hash.c/h
- Add ucl_object_iterate_end() to ucl_util.c and ucl.h
- Add ucl_iterate_object_end macro alias

Note: Rspamd already had the security fixes for:
- heap-buffer-overflow in ucl_maybe_parse_number
- heap-buffer-overflow in ucl_parse_multiline_string
- Use-After-Free in ucl_hash_insert
- Invalid JSON emission when merging objects

7 weeks ago[Feature] Add rspamd_text:normalize_newlines() for CRLF/LF conversion
Vsevolod Stakhov [Mon, 16 Feb 2026 15:00:03 +0000 (15:00 +0000)] 
[Feature] Add rspamd_text:normalize_newlines() for CRLF/LF conversion

Add fast C API and Lua binding to normalize line endings in rspamd_text:
- Two-pass algorithm using rspamd_memcspn for efficient scanning
- LF to CRLF conversion (for SMTP compliance, fixes issue #5888)
- CRLF to LF conversion (for Unix compatibility)
- Supports mempool for memory allocation
- Proper ownership handling: frees old memory if owned, sets OWN flag if using g_malloc

Update lua_smtp.lua to normalize messages to CRLF before SMTP DATA,
ensuring compatibility with strict servers like Exchange.

Includes comprehensive unit tests covering:
- No-op cases (already normalized, no newlines)
- Basic conversions in both directions
- Mixed/inconsistent line endings
- Weird line endings (lone CR, multiple CR)
- Edge cases (empty, single char, large text, null bytes)
- Mode parameter variations (crlf/windows/lf/unix, case insensitive)

7 weeks agoMerge pull request #5892 from fatalbanana/structured_meta
Vsevolod Stakhov [Mon, 16 Feb 2026 12:40:40 +0000 (12:40 +0000)] 
Merge pull request #5892 from fatalbanana/structured_meta

[Test] Don't install python libraries at runtime

7 weeks ago[Test] Don't install python libraries at runtime 5892/head
Andrew Lewis [Mon, 16 Feb 2026 11:24:25 +0000 (13:24 +0200)] 
[Test] Don't install python libraries at runtime

7 weeks agoMerge pull request #5890 from rspamd/vstakhov-uuid-v7-per-task
Vsevolod Stakhov [Sun, 15 Feb 2026 21:47:48 +0000 (21:47 +0000)] 
Merge pull request #5890 from rspamd/vstakhov-uuid-v7-per-task

Add structured metadata exporter with native UUID v7 per task

7 weeks ago[Feature] Add UUID v7 column support to ClickHouse plugin 5890/head
Vsevolod Stakhov [Sun, 15 Feb 2026 10:03:00 +0000 (10:03 +0000)] 
[Feature] Add UUID v7 column support to ClickHouse plugin

Add TaskUUID column with Delta compression codec for efficient storage
of time-ordered UUID v7 values generated natively by Rspamd.

- Add enable_uuid setting (default: false)
- Add TaskUUID UUID CODEC(Delta, LZ4) column to schema
- Add migration from schema version 9 to 10
- Collect UUID via task:get_uuid() when enabled

Delta compression is effective for UUIDv7 due to its 48-bit millisecond
timestamp prefix ensuring monotonic ordering.

7 weeks ago[Test] Add functional tests for structured metadata exporter
Vsevolod Stakhov [Sat, 14 Feb 2026 22:47:30 +0000 (22:47 +0000)] 
[Test] Add functional tests for structured metadata exporter

7 weeks ago[Test] Add unit tests for structured formatter features
Vsevolod Stakhov [Sat, 14 Feb 2026 21:43:22 +0000 (21:43 +0000)] 
[Test] Add unit tests for structured formatter features

7 weeks ago[Feature] Add zstd compression option to structured formatter
Vsevolod Stakhov [Sat, 14 Feb 2026 21:26:24 +0000 (21:26 +0000)] 
[Feature] Add zstd compression option to structured formatter

7 weeks ago[Feature] Use detected MIME types for attachments in structured formatter
Vsevolod Stakhov [Sat, 14 Feb 2026 21:22:52 +0000 (21:22 +0000)] 
[Feature] Use detected MIME types for attachments in structured formatter

7 weeks ago[Feature] Sync UUID v7 random portion with Log-Tag header
Vsevolod Stakhov [Sat, 14 Feb 2026 19:17:22 +0000 (19:17 +0000)] 
[Feature] Sync UUID v7 random portion with Log-Tag header

When an MTA provides a Log-Tag header that overrides the pool UID,
patch the task UUID's random portion (bytes 8-15) to stay in sync.
Uses a fast hash of the tag to derive the bytes while preserving
the UUID v7 variant bits.

7 weeks ago[Feature] Add structured formatter to metadata_exporter
Vsevolod Stakhov [Sat, 14 Feb 2026 15:35:59 +0000 (15:35 +0000)] 
[Feature] Add structured formatter to metadata_exporter

Add a 'structured' output format that emits rich msgpack metadata
including UUID correlation, extracted text, base64-encoded attachment
and image content, URLs, and reply detection. Uses task:get_uuid()
for cross-system correlation instead of generating UUIDs in Lua.

7 weeks ago[Feature] Add native UUID v7 per task with Lua binding
Vsevolod Stakhov [Sat, 14 Feb 2026 15:35:51 +0000 (15:35 +0000)] 
[Feature] Add native UUID v7 per task with Lua binding

Generate a UUID v7 (time-ordered, RFC 9562) natively in C at task
creation time. The task's log UID is derived from the UUID's random
portion so that UID and UUID are always correlated.

- rspamd_uuid_v7() in util.c: 48-bit ms timestamp + crypto-random bits
- task_uuid[37] field in rspamd_task, populated in rspamd_task_new()
- task:get_uuid() Lua method for plugin access

7 weeks ago[Fix] Preserve UNSCORED flag when config defines symbol without score
Vsevolod Stakhov [Fri, 13 Feb 2026 17:18:39 +0000 (17:18 +0000)] 
[Fix] Preserve UNSCORED flag when config defines symbol without score

When rspamd_config_add_symbol was called for an existing symbol without
a score (NAN), line 1811 unconditionally replaced all flags, clearing
RSPAMD_SYMBOL_FLAG_UNSCORED. This caused Lua-registered scores to be
ignored: if a symbol appeared in config (e.g. groups.conf) without a
score, the UNSCORED flag was lost, and the Lua score-setting block in
lua_config_register_symbol_from_table was skipped, leaving score at 0.

Now flags are updated correctly in both cases:
- Real score provided: flags fully replaced with UNSCORED cleared
- NAN score: flags updated but UNSCORED preserved from existing symbol

Also initialize score to NAN in lua_config_set_metric_symbol to avoid
passing uninitialized stack garbage to rspamd_config_add_symbol.

7 weeks ago[Feature] Add dual-mode HTML fuzzy: template matching + phishing detection
Vsevolod Stakhov [Fri, 13 Feb 2026 16:47:13 +0000 (16:47 +0000)] 
[Feature] Add dual-mode HTML fuzzy: template matching + phishing detection

When html_ignore_domains is enabled, generate two HTML fuzzy commands per
part: a template command (domains ignored) and a domain-sensitive command
(domains included). If the template matches but domains don't, the new
FUZZY_HTML_PHISHING symbol fires, detecting reused HTML templates with
swapped phishing links.

7 weeks ago[Fix] Load fuzzy_html_phishing rule in main rules loader
Vsevolod Stakhov [Fri, 13 Feb 2026 14:25:35 +0000 (14:25 +0000)] 
[Fix] Load fuzzy_html_phishing rule in main rules loader

7 weeks ago[Fix] Fix custom tokenizer UAF and improve CJK fuzzy detection
Vsevolod Stakhov [Fri, 13 Feb 2026 14:09:59 +0000 (14:09 +0000)] 
[Fix] Fix custom tokenizer UAF and improve CJK fuzzy detection

Fix use-after-free in custom tokenizer integration: when tokens were
shallow-copied from a custom tokenizer result, cleanup_result would free
per-token normalized/stemmed/unicode strings while the copies still
referenced them. Now copy these strings into the mempool before cleanup.

Improve fuzzy hash generation for CJK (Japanese/Chinese/Korean) text:
- Lower shingle word count threshold by 3x for CJK languages (64→21,
  floor 32→12) since CJK morphemes carry higher semantic density
- Boost text_multiplier by 3x for CJK to compensate for 3-byte UTF-8
  characters, allowing short CJK emails to pass the min_bytes gate

Previously, short Japanese phishing emails (~50 chars, ~20 words) would
generate zero fuzzy hashes — failing both the word count gate for shingles
and the byte length gate for direct hash.

7 weeks ago[Fix] Use class_name as Redis label for multiclass Bayes without class_labels config
Vsevolod Stakhov [Fri, 13 Feb 2026 10:58:25 +0000 (10:58 +0000)] 
[Fix] Use class_name as Redis label for multiclass Bayes without class_labels config

get_class_label() fell through to the legacy "S"/"H" fallback when
class_labels hash table was NULL, even when an explicit class_name
(e.g. "cold_marketing") was set on the statfile. Since all non-binary
classes have is_spam=FALSE, every class mapped to "H", causing:
- All tokens stored under the same Redis hash field "H"
- All learn counters going to learns_ham
- Classification returning identical data for all classes
- Mempool runtime caching collisions (all saved under key _H)

Fix: check class_name with !is_spam_converted before the S/H fallback
so explicit multiclass configs use their actual class name as the Redis
label, while legacy binary configs (auto-converted from spam=true/false)
still use "S"/"H".

Also fix controller learn log to show actual class name instead of
always "spam"/"ham".

7 weeks ago[Rework] Rewrite fuzzy_html_phishing rule with proper config awareness
Vsevolod Stakhov [Fri, 13 Feb 2026 10:11:25 +0000 (10:11 +0000)] 
[Rework] Rewrite fuzzy_html_phishing rule with proper config awareness

Rewrite fuzzy HTML phishing mismatch detection to read fuzzy_check
config at load time and only check symbols from rules that have
html_shingles enabled. Fix broken virtual symbol registration by
registering callback first and linking virtuals via parent id.
Skip registration entirely when no rules have html_shingles.

7 weeks ago[Fix] Resolve composite references in inverted index for fast path
Vsevolod Stakhov [Fri, 13 Feb 2026 07:37:27 +0000 (07:37 +0000)] 
[Fix] Resolve composite references in inverted index for fast path

When the inverted index fast path collects potentially active composites,
it scans symbols already in the scan result. Composite symbols are not
yet in the scan result at that point, so composites referencing other
composites as atoms were never activated and silently failed to fire.

Fix by resolving composite references at index build time: recursively
collect leaf (non-composite) atoms and propagate dependent composites
to those atoms' index entries. Also refactor atom name parsing into a
shared helper to reduce duplication.

7 weeks ago[Fix] Remove check for non-existent fuzzy_result mempool variable
Vsevolod Stakhov [Fri, 13 Feb 2026 07:24:50 +0000 (07:24 +0000)] 
[Fix] Remove check for non-existent fuzzy_result mempool variable

The fuzzy_result mempool variable is never set by fuzzy_check, so the
early return was always triggered, making the phishing mismatch check
a no-op. The actual logic uses get_symbols_all() which works correctly.

7 weeks ago[Feature] Add ignore_link_domains option for HTML fuzzy rules
Vsevolod Stakhov [Fri, 13 Feb 2026 07:23:20 +0000 (07:23 +0000)] 
[Feature] Add ignore_link_domains option for HTML fuzzy rules

Allow HTML fuzzy shingles to match purely on structure (tag skeleton +
classes) by stripping link domains from structural tokens. Domain hashes
are still computed separately for the metadata fields. A separate cache
key suffix (_nd) prevents cross-contamination with normal hashes.

8 weeks ago[Fix] Handle native boolean values in lua_util.toboolean()
Vsevolod Stakhov [Thu, 12 Feb 2026 17:35:32 +0000 (17:35 +0000)] 
[Fix] Handle native boolean values in lua_util.toboolean()

toboolean() only handled string and number inputs, falling through to
the error branch for native Lua booleans and always returning false.
This broke the fuzzy_check "checks" configuration block since UCL
converts boolean values to native Lua booleans, and apply_checks_overrides
in lua_fuzzy.lua passes them through toboolean() via bool_opt().

Fixes: #5775
8 weeks ago[Minor] Try to fix CC issue with tabs
Vsevolod Stakhov [Thu, 12 Feb 2026 16:27:21 +0000 (16:27 +0000)] 
[Minor] Try to fix CC issue with tabs

8 weeks agoMerge pull request #5885 from rspamd/vstakhov-lua-perl-utils
Vsevolod Stakhov [Thu, 12 Feb 2026 10:42:43 +0000 (10:42 +0000)] 
Merge pull request #5885 from rspamd/vstakhov-lua-perl-utils

[Feature] Rewrite rspamd_stats.pl and mapstats.pl as rspamadm Lua subcommands

8 weeks ago[Fix] Fix issues in logstats/mapstats from code review 5885/head
Vsevolod Stakhov [Thu, 12 Feb 2026 10:00:14 +0000 (10:00 +0000)] 
[Fix] Fix issues in logstats/mapstats from code review

- Shell-quote paths in io.popen() to prevent injection
- Fix typo: correllations -> correlations in JSON output
- Pre-compile ignored symbol regexes instead of recompiling per call
- Deduplicate score change output logic in logstats
- Use native rspamd_ip equality instead of string comparison in mapstats

8 weeks ago[Fix] Use fuzzy group and options instead of hardcoded symbol names for phishing...
Vsevolod Stakhov [Wed, 11 Feb 2026 12:19:39 +0000 (12:19 +0000)] 
[Fix] Use fuzzy group and options instead of hardcoded symbol names for phishing detection

Detect text/html fuzzy matches by checking the symbol group ('fuzzy')
and parsing the type from symbol options (flag:hash:prob:type) rather
than pattern-matching on symbol names that may not exist.

8 weeks ago[Test] Add functional tests for logstats and mapstats
Vsevolod Stakhov [Wed, 11 Feb 2026 11:06:54 +0000 (11:06 +0000)] 
[Test] Add functional tests for logstats and mapstats

Robot Framework tests covering:
- logstats: JSON output, text output, symbol filter, alpha_score
  warning, stdin mode, scan time display
- mapstats: map loading, inline comments for plain/IP/regexp maps,
  match counts, regexp matching

Includes test data: sample log files, plain/IP/regexp map files,
and a minimal multimap config.

8 weeks ago[Fix] Fix missing inline comments in mapstats output
Vsevolod Stakhov [Wed, 11 Feb 2026 09:54:30 +0000 (09:54 +0000)] 
[Fix] Fix missing inline comments in mapstats output

rspamd_regexp_search() truncates captures at the first unmatched
optional group, so when the score group was absent the comment
group was lost. Extract comments with Lua patterns before passing
the line body to rspamd_regexp.

8 weeks ago[Minor] Add colored output and TTY-aware progress to logstats/mapstats
Vsevolod Stakhov [Wed, 11 Feb 2026 09:25:31 +0000 (09:25 +0000)] 
[Minor] Add colored output and TTY-aware progress to logstats/mapstats

Gate spinner and ANSI escape codes behind isatty() so piped output is
clean. Add ansicolors to logstats (Ham/Spam/Junk labels, symbol names,
actions, warnings, summary) and mapstats (map status, match counts,
unmatched warnings).

8 weeks ago[Minor] Warn when symbols are filtered by alpha_score
Vsevolod Stakhov [Wed, 11 Feb 2026 09:12:10 +0000 (09:12 +0000)] 
[Minor] Warn when symbols are filtered by alpha_score

8 weeks ago[Minor] Handle blank lines in mapstats maps
Alexander Moisseev [Wed, 11 Feb 2026 06:41:23 +0000 (09:41 +0300)] 
[Minor] Handle blank lines in mapstats maps

Replace regex-based empty line detection with Lua pattern matching
to correctly identify and preserve blank lines instead of treating
them as syntax errors.

8 weeks ago[Minor] Use positional argument for log file in logstats/mapstats
Vsevolod Stakhov [Wed, 11 Feb 2026 09:05:50 +0000 (09:05 +0000)] 
[Minor] Use positional argument for log file in logstats/mapstats

8 weeks ago[Fix] Fix broken ip_within in mapstats: parse CIDR and use apply_mask return value
Vsevolod Stakhov [Tue, 10 Feb 2026 20:47:10 +0000 (20:47 +0000)] 
[Fix] Fix broken ip_within in mapstats: parse CIDR and use apply_mask return value

rspamd_ip.from_string rejects '/' in CIDR notation, so strip the mask
before parsing. Also apply_mask returns a new IP object rather than
modifying in place, so capture the return values.

8 weeks ago[Feature] Rewrite rspamd_stats.pl and mapstats.pl as rspamadm Lua subcommands
Vsevolod Stakhov [Tue, 10 Feb 2026 20:10:43 +0000 (20:10 +0000)] 
[Feature] Rewrite rspamd_stats.pl and mapstats.pl as rspamadm Lua subcommands

Add rspamadm logstats and rspamadm mapstats commands that replace the
Perl utility scripts utils/rspamd_stats.pl and utils/mapstats.pl.

- lua_log_utils.lua: shared library for log format detection, timestamp
  conversion, compressed file handling, directory scanning, and progress
  spinner
- logstats.lua: full port of rspamd_stats.pl with all options including
  symbol filtering, bidirectional symbols, groups, correlations, score
  multipliers, time range filtering, and JSON output via UCL
- mapstats.lua: full port of mapstats.pl using native rspamd_config for
  multimap access, rspamd_regexp for regex maps with full flag support,
  and rspamd_ip for IP/CIDR matching (no external dependencies)

8 weeks ago[Test] Add unit tests for ring hash consistent upstream hashing
Vsevolod Stakhov [Tue, 10 Feb 2026 15:00:22 +0000 (15:00 +0000)] 
[Test] Add unit tests for ring hash consistent upstream hashing

Verify consistency, distribution, weight-scaling, stability, and
except-parameter behaviour of the Ketama-style ring hash introduced
in 4ea750466.

8 weeks ago[Rework] Replace broken Jump Hash with Ring Hash (Ketama) for consistent upstream...
Vsevolod Stakhov [Tue, 10 Feb 2026 14:52:30 +0000 (14:52 +0000)] 
[Rework] Replace broken Jump Hash with Ring Hash (Ketama) for consistent upstream hashing

Jump Consistent Hash (Lamping & Veach 2014) only handles bucket
addition/removal at the end of the range.  When an upstream in the
middle failed, the old code rehashed with mum_hash_step and retried
up to 20 times, which destroyed the consistency property: keys that
mapped to the dead node were redistributed randomly instead of
deterministically, and didn't return when the node recovered.

Replace with a Ketama-style ring hash:
- Each alive upstream gets MAX(weight,1)*100 virtual nodes on a
  sorted hash ring (keyed by name, order-independent).
- Lookup is a binary search: O(log(n*v)) instead of O(ln n) * retries.
- When an upstream fails, only its ~1/n fraction of keys slide to the
  next ring point — true minimal disruption.
- When it recovers, the same keys return — true consistency.
- The 'except' parameter walks forward on the ring instead of rehashing.
- Ring is rebuilt lazily (dirty flag set on active/inactive transitions).

8 weeks agoMerge pull request #5884 from rspamd/vstakhov-ssl-server
Vsevolod Stakhov [Tue, 10 Feb 2026 14:30:51 +0000 (14:30 +0000)] 
Merge pull request #5884 from rspamd/vstakhov-ssl-server

Implement HTTPS server support for workers

8 weeks agoMerge pull request #5883 from moisseev/webui
Vsevolod Stakhov [Tue, 10 Feb 2026 14:18:20 +0000 (14:18 +0000)] 
Merge pull request #5883 from moisseev/webui

[Minor] Update RequireJS to 2.3.8

8 weeks agoMerge pull request #5870 from moisseev/mapstats
Vsevolod Stakhov [Tue, 10 Feb 2026 14:18:09 +0000 (14:18 +0000)] 
Merge pull request #5870 from moisseev/mapstats

[Feature] Add mapstats utility for multimap statistics analysis

8 weeks ago[Fix] Fix proxy mirror SSL/keepalive config parsing and remove duplicate keepalive... 5884/head
Vsevolod Stakhov [Mon, 9 Feb 2026 15:33:24 +0000 (15:33 +0000)] 
[Fix] Fix proxy mirror SSL/keepalive config parsing and remove duplicate keepalive block

Add missing ssl and keepalive option parsing to mirror config parser,
and remove duplicate keepalive parsing block in upstream config parser.

8 weeks ago[Test] Add SSL server functional tests
Vsevolod Stakhov [Mon, 9 Feb 2026 14:35:01 +0000 (14:35 +0000)] 
[Test] Add SSL server functional tests

Add functional tests for HTTPS server support in the
merged test suite. Tests cover controller and normal
worker SSL endpoints plus plain HTTP coexistence.

8 weeks ago[Feature] Auto-detect SSL from bind sockets, remove ssl = true option
Vsevolod Stakhov [Mon, 9 Feb 2026 14:34:47 +0000 (14:34 +0000)] 
[Feature] Auto-detect SSL from bind sockets, remove ssl = true option

Instead of requiring a separate `ssl = true` worker option, automatically
detect SSL need by checking if any bind socket has the ssl flag. Emit an
error if SSL bind sockets are configured but ssl_cert/ssl_key are missing.

8 weeks ago[Fix] Fix bind line parsing to use stripped bind_line for SSL suffix
Vsevolod Stakhov [Mon, 9 Feb 2026 11:54:04 +0000 (11:54 +0000)] 
[Fix] Fix bind line parsing to use stripped bind_line for SSL suffix

When parsing bind lines with " ssl" suffix, the suffix was stripped from
cnf->bind_line but the original unstripped str was passed to
rspamd_parse_host_port_priority, causing parse failures.

8 weeks ago[Feature] Implement HTTPS server support for workers
Vsevolod Stakhov [Mon, 9 Feb 2026 10:44:36 +0000 (10:44 +0000)] 
[Feature] Implement HTTPS server support for workers

Wire up server-side SSL/TLS for HTTP workers, building on the recently
added rspamd_ssl_accept_fd() infrastructure. This enables HTTPS for
controller, normal, and proxy workers with per-bind-address granularity.

Configuration: `bind_socket = "*:11335 ssl"` plus `ssl_cert` and
`ssl_key` worker options.

- Add rspamd_init_ssl_ctx_server() for server SSL_CTX with cert+key
- Parse trailing " ssl" suffix in bind_socket lines
- Propagate is_ssl flag through bind conf to listen sockets
- Add rspamd_http_connection_accept_ssl() for async SSL handshake
- Fix write_message_common to handle server-side SSL responses
- Add SSL support to HTTP router (set_ssl, handle_socket_ssl)
- Wire up SSL in controller, normal worker, and proxy worker
- Add rspamd_worker_is_ssl_socket() utility for fd-to-SSL lookup

8 weeks ago[Minor] Add CLAUDE.md with development guidelines
Vsevolod Stakhov [Mon, 9 Feb 2026 09:16:29 +0000 (09:16 +0000)] 
[Minor] Add CLAUDE.md with development guidelines

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
8 weeks ago[Feature] Add SSL server-side accept support
Vsevolod Stakhov [Sun, 8 Feb 2026 19:25:44 +0000 (19:25 +0000)] 
[Feature] Add SSL server-side accept support

Add rspamd_ssl_accept_fd() function for server-side SSL handshakes:
- Mirrors existing rspamd_ssl_connect_fd() but for accepting connections
- Adds ssl_conn_init_accept state for server-side SSL state machine
- Handles SSL_accept() with proper WANT_READ/WANT_WRITE event handling

This enables SSL-capable server implementations (e.g. SMTP proxy with STARTTLS).

8 weeks agoMerge pull request #5880 from rspamd/vstakhov-check-v3
Vsevolod Stakhov [Sun, 8 Feb 2026 19:30:44 +0000 (19:30 +0000)] 
Merge pull request #5880 from rspamd/vstakhov-check-v3

Add /checkv3 multipart scan endpoint

8 weeks ago[Test] Add v3 compression and proxy forwarding tests 5880/head
Vsevolod Stakhov [Sun, 8 Feb 2026 14:21:09 +0000 (14:21 +0000)] 
[Test] Add v3 compression and proxy forwarding tests

Add C++ unit tests for zstd per-part compression round-trip
(serialize and iov paths), mixed compressed/uncompressed parts,
and body_iov segment writability for in-place encryption.

Add Robot functional tests for /checkv3 through the proxy,
both direct multipart and rspamc with zstd compression.

8 weeks ago[Fix] protocol: Handle shared memory and whole-body compression for v3 proxy path
Vsevolod Stakhov [Sun, 8 Feb 2026 14:20:45 +0000 (14:20 +0000)] 
[Fix] protocol: Handle shared memory and whole-body compression for v3 proxy path

When the proxy forwards /checkv3 requests to a local upstream, it uses
shared memory (GET + Shm headers) instead of sending the body inline.
The v3 request handler only read from chunk/len parameters which are
empty in this case. Add Shm/Shm-Offset/Shm-Length header handling to
read the body from the shared memory segment.

Additionally, the proxy may compress the entire response body with zstd
before forwarding to the client. The v3 client finish handler parsed
multipart directly from the compressed body_buf. Add whole-body
decompression (matching the v2 handler) before multipart parsing.

8 weeks ago[Feature] protocol: Zero-copy piecewise writev for v3 multipart responses
Vsevolod Stakhov [Sun, 8 Feb 2026 12:18:16 +0000 (12:18 +0000)] 
[Feature] protocol: Zero-copy piecewise writev for v3 multipart responses

Add body_iov support to the HTTP message layer so the write path can use
writev with multiple iovec segments instead of a single contiguous buffer.
The v3 multipart response now builds its boundary/header strings and data
pointers as separate iovecs, avoiding extra copies of the UCL result and
rewritten message body. The cryptobox encryption path handles multiple body
segments via encryptv_nm_inplace seamlessly.

2 months ago[Feature] protocol: Add v3 multipart response parsing for proxy and body decompression
Vsevolod Stakhov [Sun, 8 Feb 2026 10:13:40 +0000 (10:13 +0000)] 
[Feature] protocol: Add v3 multipart response parsing for proxy and body decompression

Proxy forwarding now handles multipart/mixed responses from /checkv3:
parse result+body parts, decompress zstd, detect msgpack, and forward
rewritten body to milter. Self-scan v3 populates conn->results for
milter and Lua comparison scripts. rspamc client decompresses zstd
body parts returned by the server.

2 months ago[Refactor] protocol: Deduplicate v2/v3 request and reply handling
Vsevolod Stakhov [Sat, 7 Feb 2026 21:04:44 +0000 (21:04 +0000)] 
[Refactor] protocol: Deduplicate v2/v3 request and reply handling

Extract shared helpers to eliminate duplicated logic between
rspamd_protocol_handle_headers (v2) and rspamd_protocol_handle_metadata (v3),
as well as between rspamd_protocol_http_reply and rspamd_protocol_http_reply_v3.

Request-side helpers: rspamd_protocol_set_from_envelope,
rspamd_protocol_set_ip, rspamd_protocol_set_settings_id,
rspamd_protocol_set_log_tag, rspamd_protocol_add_mail_esmtp_arg,
rspamd_protocol_add_rcpt_esmtp_arg.

Reply-side helpers: rspamd_protocol_update_history_and_log,
rspamd_protocol_update_stats, rspamd_protocol_get_rewritten_body.

2 months ago[Feature] rspamc: Add --msgpack flag for v3 protocol
Vsevolod Stakhov [Sat, 7 Feb 2026 15:55:53 +0000 (15:55 +0000)] 
[Feature] rspamc: Add --msgpack flag for v3 protocol

Add --msgpack option to rspamc that sends metadata as msgpack instead
of JSON and requests msgpack responses when using --protocol-v3.

The client serializes metadata via UCL_EMIT_MSGPACK, sets the metadata
part Content-Type to application/msgpack, and sends Accept:
application/msgpack so the server returns results in msgpack format.

Add functional tests for rspamc v3 with zstd compression, httpcrypt
encryption, msgpack metadata, and encrypted+msgpack combinations.

2 months ago[Fix] protocol: Pass v3 Content-Type as mime_type parameter
Vsevolod Stakhov [Sat, 7 Feb 2026 15:54:55 +0000 (15:54 +0000)] 
[Fix] protocol: Pass v3 Content-Type as mime_type parameter

The v3 reply builder was adding Content-Type (multipart/mixed with
boundary) as an HTTP header via rspamd_http_message_add_header, while
setting ctype=NULL for rspamd_http_connection_write_message. With NULL,
the HTTP library defaults to "text/plain", so the client never saw the
multipart Content-Type and fell through to plain UCL parsing.

Fix by returning the Content-Type string (pool-allocated) from
rspamd_protocol_http_reply_v3 and passing it as the mime_type parameter
directly. Also fix the same pattern in rspamd_proxy.c.

Update v3 error test expectations from 400 to 500 to match the existing
error code mapping formula (500 + err_code % 100).

2 months ago[Fix] Add missing includes for Linux/GCC build
Vsevolod Stakhov [Sat, 7 Feb 2026 13:34:27 +0000 (13:34 +0000)] 
[Fix] Add missing includes for Linux/GCC build

Add <cctype> for std::tolower and <string> for std::string
in multipart_form.cxx. These are transitively included on
macOS/clang but not on Linux/GCC.

2 months ago[Test] Add MIME-in-message tests for /checkv3
Vsevolod Stakhov [Sat, 7 Feb 2026 13:33:24 +0000 (13:33 +0000)] 
[Test] Add MIME-in-message tests for /checkv3

Verify that messages with their own MIME structure (multipart/alternative,
multipart/mixed with attachments) are preserved intact when wrapped in
the outer form-data envelope. Unit tests confirm inner MIME boundaries
don't confuse the outer parser; functional tests confirm end-to-end
symbol detection (R_PARTS_DIFFER, MIME_HTML_ONLY) works via /checkv3.

2 months ago[Test] Add tests for /checkv3 multipart endpoint
Vsevolod Stakhov [Sat, 7 Feb 2026 12:23:37 +0000 (12:23 +0000)] 
[Test] Add tests for /checkv3 multipart endpoint

C++ unit tests (23 cases): multipart form parser, response builder,
and round-trip serialization. Robot Framework functional tests (6 cases):
GTUBE scan, metadata handling, settings_id, and error cases for missing
parts and malformed boundaries. Python helpers for building and parsing
multipart/form-data requests and multipart/mixed responses.

2 months ago[Feature] Add v3 request validation and use safe UCL parser flags
Vsevolod Stakhov [Sat, 7 Feb 2026 12:22:22 +0000 (12:22 +0000)] 
[Feature] Add v3 request validation and use safe UCL parser flags

Enforce max 2 parts (metadata + message) in /checkv3 multipart requests,
returning HTTP 400 for malformed requests with extra parts. Switch UCL
parser to UCL_PARSER_SAFE_FLAGS to disable macros/includes in untrusted
metadata input.

2 months agoMerge branch 'master' into vstakhov-check-v3
Vsevolod Stakhov [Sat, 7 Feb 2026 11:19:47 +0000 (11:19 +0000)] 
Merge branch 'master' into vstakhov-check-v3

2 months ago[Fix] tests: Update URL expectation to match percent-encoded spaces
Vsevolod Stakhov [Sat, 7 Feb 2026 09:57:57 +0000 (09:57 +0000)] 
[Fix] tests: Update URL expectation to match percent-encoded spaces

After 9f3a41069 URL tostring re-encodes spaces as %20, so the
functional test must expect the encoded form.

2 months ago[Minor] Update RequireJS to 2.3.8 5883/head
Alexander Moisseev [Sat, 7 Feb 2026 09:27:34 +0000 (12:27 +0300)] 
[Minor] Update RequireJS to 2.3.8

2 months ago[Test] Add MIME_HTML_ONLY test for multipart/mixed with html and non-text attachment
Vsevolod Stakhov [Fri, 6 Feb 2026 18:16:03 +0000 (18:16 +0000)] 
[Test] Add MIME_HTML_ONLY test for multipart/mixed with html and non-text attachment

Add test case for multipart/mixed containing text/html + application/zip
to ensure MIME_HTML_ONLY fires when HTML is the only text part alongside
a non-text attachment.

2 months ago[Fix] lua_content: Move PDF ligature substitutions from string unescape to text handler
Vsevolod Stakhov [Fri, 6 Feb 2026 17:42:55 +0000 (17:42 +0000)] 
[Fix] lua_content: Move PDF ligature substitutions from string unescape to text handler

StandardEncoding/MacRomanEncoding ligature substitutions (e.g. byte 0xAD -> 'ffl')
were applied to all PDF strings including /URI annotation values. This corrupted
soft hyphens (U+00AD) in URLs, preventing the URL parser from detecting zero-width
space obfuscation and setting the ZW_SPACES flag.

Move ligature substitutions to text_op_handler where they belong, so they only
apply to rendered text content (Tj/TJ operators), not to dictionary string values.

2 months ago[Feature] arc: Add trusted_authserv_id option for reuse_auth_results
Vsevolod Stakhov [Fri, 6 Feb 2026 15:31:46 +0000 (15:31 +0000)] 
[Feature] arc: Add trusted_authserv_id option for reuse_auth_results

Allow configuring which Authentication-Results header to trust when
reuse_auth_results is enabled, by matching the authserv-id field.

Closes #5881

2 months ago[Fix] lua_url: Re-encode control characters and spaces in URL tostring
Vsevolod Stakhov [Fri, 6 Feb 2026 15:11:44 +0000 (15:11 +0000)] 
[Fix] lua_url: Re-encode control characters and spaces in URL tostring

The URL parser (rspamd_url_decode) decodes percent-encoded sequences
like %20 back to literal characters in the internal representation.
When tostring() returned these decoded URLs, spaces and control chars
would break subsequent re-parsing (e.g., in url_redirector redirect
chains and Redis cache round-trips). Fix by re-encoding characters
<= 0x20 on serialization, matching browser behavior: decode internally
for matching, re-encode on copy.

2 months ago[Fix] re_cache: Always use charset-converted content for SARAWBODY matching
Vsevolod Stakhov [Fri, 6 Feb 2026 11:22:07 +0000 (11:22 +0000)] 
[Fix] re_cache: Always use charset-converted content for SARAWBODY matching

Use utf_raw_content (charset-converted UTF-8 with HTML tags preserved)
for all SARAWBODY patterns, regardless of /u flag presence. The previous
approach used utf_content (which strips HTML tags on HTML parts) and only
for classes containing /u patterns, leaving non-/u patterns matching
against raw bytes in the original charset.

This prevents trivial bypass of SA rawbody rules via exotic encodings
like UTF-16 and ensures consistent matching across PCRE and Hyperscan.
Falls back to transfer-decoded parsed content only when charset
conversion failed.

2 months agoMerge pull request #5871 from KIT-CERT/fix_ratelimits
Vsevolod Stakhov [Fri, 6 Feb 2026 10:17:38 +0000 (10:17 +0000)] 
Merge pull request #5871 from KIT-CERT/fix_ratelimits

fix dynamic bucket-specific rate-limits

2 months agoMerge pull request #5874 from rspamd/vstakhov-proxy-balancing
Vsevolod Stakhov [Fri, 6 Feb 2026 10:17:15 +0000 (10:17 +0000)] 
Merge pull request #5874 from rspamd/vstakhov-proxy-balancing

Feature: Token bucket load balancing for proxy upstreams

2 months ago[Test] upstream: add token bucket unit tests 5874/head
Vsevolod Stakhov [Fri, 6 Feb 2026 09:26:39 +0000 (09:26 +0000)] 
[Test] upstream: add token bucket unit tests

15 doctest test cases covering token bucket load balancing:
basic selection, cost formula, token return/penalty, least-loaded
preference, except parameter, exhaustion fallback, fair distribution,
custom config, empty list, null safety, large messages, multiple
inflight, mixed success/failure, and generic API fallback.

2 months ago[Fix] upstream: fix stale heap_idx in token bucket
Vsevolod Stakhov [Fri, 6 Feb 2026 09:25:17 +0000 (09:25 +0000)] 
[Fix] upstream: fix stale heap_idx in token bucket

The intrusive heap swaps entire structs during swim/sink, making
up->heap_idx stale after any heap modification. The update function
would silently skip updates when the cached index pointed to a
different upstream, breaking load distribution across backends.

Fix by falling back to linear search on cache miss and refreshing
heap_idx after every heap update. Also add underflow warning for
double-return detection and improve API documentation.

2 months agoMerge branch 'master' into vstakhov-proxy-balancing
Vsevolod Stakhov [Fri, 6 Feb 2026 08:07:36 +0000 (08:07 +0000)] 
Merge branch 'master' into vstakhov-proxy-balancing

2 months ago[Feature] Add /checkv3 multipart scan endpoint
Vsevolod Stakhov [Thu, 5 Feb 2026 22:00:00 +0000 (22:00 +0000)] 
[Feature] Add /checkv3 multipart scan endpoint

Implement a new /checkv3 endpoint that uses multipart/form-data for
requests and multipart/mixed for responses. Metadata (from, rcpt, ip,
settings, etc.) is sent as a structured JSON/msgpack part instead of
HTTP headers. The response includes a "result" part and an optional
"body" part for rewritten messages.

New C++ multipart parser and response builder with C bridge functions.
Per-part zstd compression support. Client-side support via rspamc
--protocol-v3 flag. Proxy self-scan path updated for v3.

2 months ago[Refactor] fuzzy storage: split helper code (#5875)
Vsevolod Stakhov [Thu, 5 Feb 2026 15:38:07 +0000 (15:38 +0000)] 
[Refactor] fuzzy storage: split helper code (#5875)

2 months agoMerge pull request #5878 from moisseev/webui
Vsevolod Stakhov [Thu, 5 Feb 2026 14:52:20 +0000 (14:52 +0000)] 
Merge pull request #5878 from moisseev/webui

[Fix] WebUI: Allow computing fuzzy hashes without writable storages

2 months ago[Fix] Fix printf format specifiers found by clang-plugin
Vsevolod Stakhov [Thu, 5 Feb 2026 14:05:32 +0000 (14:05 +0000)] 
[Fix] Fix printf format specifiers found by clang-plugin

2 months ago[Fix] clang-plugin: add null check for struct type in check_struct_type
Vsevolod Stakhov [Thu, 5 Feb 2026 14:04:57 +0000 (14:04 +0000)] 
[Fix] clang-plugin: add null check for struct type in check_struct_type

2 months ago[Fix] clang-plugin: suppress noisy remarks and fix SANITIZER macro conflict
Vsevolod Stakhov [Thu, 5 Feb 2026 13:10:54 +0000 (13:10 +0000)] 
[Fix] clang-plugin: suppress noisy remarks and fix SANITIZER macro conflict

2 months ago[Fix] clang-plugin: fix build with modern LLVM/Clang
Vsevolod Stakhov [Thu, 5 Feb 2026 13:07:03 +0000 (13:07 +0000)] 
[Fix] clang-plugin: fix build with modern LLVM/Clang

2 months ago[Fix] Use %ud instead of %u in rspamd printf format strings
Vsevolod Stakhov [Thu, 5 Feb 2026 12:44:03 +0000 (12:44 +0000)] 
[Fix] Use %ud instead of %u in rspamd printf format strings

2 months ago[Fix] re_cache: Use debug level for missing Lua backend during config
Vsevolod Stakhov [Thu, 5 Feb 2026 09:47:44 +0000 (09:47 +0000)] 
[Fix] re_cache: Use debug level for missing Lua backend during config

During config initialization (configtest, startup), there's no event
loop available so the Lua backend cannot be initialized. This is
expected behavior - use debug level when try_load=true to avoid
noisy warnings during configtest.

2 months ago[Test] Add test cases for MIME_HTML_ONLY with malformed multipart
Vsevolod Stakhov [Thu, 5 Feb 2026 09:23:54 +0000 (09:23 +0000)] 
[Test] Add test cases for MIME_HTML_ONLY with malformed multipart

Add tests for edge cases that caused a segfault when multipart/related
has no children or contains only non-text content:

- alternative-nested-rfc822.eml: multipart/alternative with HTML and
  related containing only image (no text), plus nested message/rfc822
- alternative-empty-related.eml: multipart/alternative with malformed
  related that has no proper MIME children

These test cases verify the NULL check fix for mp->children.

2 months ago[Fix] message: Add NULL check for mp->children in alternative detection
Vsevolod Stakhov [Thu, 5 Feb 2026 09:17:47 +0000 (09:17 +0000)] 
[Fix] message: Add NULL check for mp->children in alternative detection

The multipart children array can be NULL in some edge cases. Add NULL
checks before accessing mp->children->len to prevent segfault in
rspamd_mime_part_find_text_in_subtree() and related code paths.

2 months ago[Fix] re_cache: Use debug level for startup hyperscan load failures
Vsevolod Stakhov [Thu, 5 Feb 2026 09:14:22 +0000 (09:14 +0000)] 
[Fix] re_cache: Use debug level for startup hyperscan load failures

During worker startup, a "best-effort" synchronous hyperscan load is
attempted before hs_helper has finished compiling. When files don't
exist yet, the "no valid expressions" message was logged at info level,
which is noisy and misleading since this is expected startup behavior.

Changed to use debug level when try_load=true (startup probe), while
keeping info level for actual failures. Workers will receive async
notifications when hs_helper finishes compiling.

2 months ago[Fix] WebUI: Allow computing fuzzy hashes without writable storages 5878/head
Alexander Moisseev [Thu, 5 Feb 2026 09:06:48 +0000 (12:06 +0300)] 
[Fix] WebUI: Allow computing fuzzy hashes without writable storages

2 months ago[Fix] re_cache: Respect disable_hyperscan option in loading functions
Vsevolod Stakhov [Thu, 5 Feb 2026 08:58:53 +0000 (08:58 +0000)] 
[Fix] re_cache: Respect disable_hyperscan option in loading functions

Add checks for disable_hyperscan at the start of hyperscan loading
functions to prevent database loading when the option is set.

Previously, hyperscan databases would still be loaded even with
disable_hyperscan = true, causing unnecessary I/O and memory usage.

2 months ago[Fix] re_cache: Use charset-converted content for UTF-8 SARAWBODY patterns
Vsevolod Stakhov [Thu, 5 Feb 2026 08:53:07 +0000 (08:53 +0000)] 
[Fix] re_cache: Use charset-converted content for UTF-8 SARAWBODY patterns

When SARAWBODY regexp class contains UTF-8 patterns (/u flag), use
utf_content (charset-converted UTF-8 with HTML preserved) instead of
parsed content. This allows Unicode patterns like \x{200b} to match
correctly.

For non-UTF patterns, continue using parsed content with raw mode
for backward compatibility with raw byte matching.

This fixes "bad utf8 input for JIT re" errors when using Unicode
patterns in rawbody rules on non-UTF-8 encoded messages.