]> git.ipfire.org Git - thirdparty/rspamd.git/log
thirdparty/rspamd.git
9 days ago[Test] Isolate url_suspect tests with symbols_enabled 5758/head
Vsevolod Stakhov [Fri, 21 Nov 2025 11:58:11 +0000 (11:58 +0000)] 
[Test] Isolate url_suspect tests with symbols_enabled

Use symbols_enabled setting to test only specific url_suspect symbols,
preventing interference from other rules like greylist.

9 days ago[Performance] Optimize url_suspect for high URL volume messages
Vsevolod Stakhov [Fri, 21 Nov 2025 11:31:14 +0000 (11:31 +0000)] 
[Performance] Optimize url_suspect for high URL volume messages

Performance improvements for messages with many URLs:

1. O(1) TLD lookups: Convert builtin_suspicious list to hash set on init,
   eliminates O(n*m) iteration (500k+ checks for 100k URLs × 5 TLDs)

2. Use rspamd_text for URL checks: get_text(true) returns opaque rspamd_text
   without string copying, use text:find() for RTL detection

3. Use rspamd_ip API: parse_addr() + is_local() for IP checks instead of
   pattern matching

4. Add max_urls limit (10000) for DoS protection

These optimizations significantly reduce memory allocation and CPU usage.

9 days ago[Fix] Fix url_suspect plugin causing massive false positives
Vsevolod Stakhov [Fri, 21 Nov 2025 11:12:55 +0000 (11:12 +0000)] 
[Fix] Fix url_suspect plugin causing massive false positives

The url_suspect plugin had multiple critical issues:

1. R_SUSPICIOUS_URL triggered on every message with URLs, adding 25 points
   due to incorrect dynamic score usage (5.0 * 5.0 instead of 1.0 * 5.0)

2. Broken compat_mode inserted R_SUSPICIOUS_URL without URL info whenever
   ANY url check triggered, making it impossible to debug

3. Symbol names were unnecessarily configurable, adding complexity

4. url_suspect_group.conf was not included in groups.conf, so scores
   were not loaded at all

Fixed by:
- Removed R_SUSPICIOUS_URL and compat_mode completely
- Fixed all insert_result() calls to use 1.0 dynamic weight
- Made symbol names hardcoded constants
- Added url group to groups.conf with max_score = 9.0
- Cleaned up score configuration parameters

10 days agoMerge pull request #5754 from rspamd/vstakhov-rework-tableshape
Vsevolod Stakhov [Thu, 20 Nov 2025 13:09:01 +0000 (13:09 +0000)] 
Merge pull request #5754 from rspamd/vstakhov-rework-tableshape

[Feature] Add lua_shape validation library as tableshape replacement

10 days agoMerge pull request #5757 from rspamd/vstakhov-spf-flattener
Vsevolod Stakhov [Thu, 20 Nov 2025 12:59:22 +0000 (12:59 +0000)] 
Merge pull request #5757 from rspamd/vstakhov-spf-flattener

[Feature] Add SPF flattening tool with macro preservation

10 days ago[Fix] Prevent infinite loop in split_networks_into_chunks() 5757/head
Vsevolod Stakhov [Thu, 20 Nov 2025 12:32:33 +0000 (12:32 +0000)] 
[Fix] Prevent infinite loop in split_networks_into_chunks()

If a single IP network entry exceeds max_record_length (450 chars) on its own,
the code would enter an infinite loop. Added validation to check if individual
items can fit before attempting to add them to chunks. Items that are too large
are now skipped with a warning message.

10 days ago[Feature] Add SPF flattening tool with macro preservation
Vsevolod Stakhov [Thu, 20 Nov 2025 11:43:40 +0000 (11:43 +0000)] 
[Feature] Add SPF flattening tool with macro preservation

- Add new 'spf-flatten' command to dns_tool for optimizing SPF records
- Introduce RSPAMD_SPF_FLAG_MACRO_UNRESOLVED flag to preserve SPF macros
- Prevent macro expansion when sender IP is unavailable (flatten mode)
- SPF elements with macros (exists:, a:, mx:, ptr:) now preserved correctly
- Add multiple output formats: default, json, compact (BIND-style)
- Optimize IP addresses by removing default /32 and /128 masks
- Automatically split large SPF records into multiple includes
- Preserve qualifiers and 'all' mechanism in flattened records

11 days ago[Fix] Fix memory leak in custom tokenizer result handling
Vsevolod Stakhov [Wed, 19 Nov 2025 17:19:40 +0000 (17:19 +0000)] 
[Fix] Fix memory leak in custom tokenizer result handling

Free dynamically allocated kvec array after copying tokens to avoid
memory leak when using custom tokenizers with exceptions.

11 days ago[Fix] Fix lua_shape registry to recursively resolve nested schemas 5754/head
Vsevolod Stakhov [Wed, 19 Nov 2025 16:20:57 +0000 (16:20 +0000)] 
[Fix] Fix lua_shape registry to recursively resolve nested schemas

The registry's resolve_schema function was not recursively resolving
field schemas and opts.extra in table nodes, causing mixins in nested
one_of variants to never be expanded. This broke external_relay plugin
validation where rule variants with mixins were reported as having
unknown fields.

Now recursively resolves all nested schemas including field schemas,
opts.extra, and ensures mixins are properly expanded throughout the
entire schema tree.

11 days ago[Fix] Fix test files to handle missing map env vars
Vsevolod Stakhov [Wed, 19 Nov 2025 14:03:15 +0000 (14:03 +0000)] 
[Fix] Fix test files to handle missing map env vars

- Add defensive checks in maps_kv.lua to skip map creation if env vars not set
- Ensure test config file is always saved to robot-save directory

Fixes issue where external_relay test would crash because maps_kv.lua tried
to create maps with nil URLs when RADIX_MAP/MAP_MAP/REGEXP_MAP env vars
were not defined.

11 days ago[Fix] Preserve metatables in shallowcopy and save test configs
Vsevolod Stakhov [Wed, 19 Nov 2025 12:44:15 +0000 (12:44 +0000)] 
[Fix] Preserve metatables in shallowcopy and save test configs

- Fix shallowcopy to preserve metatables when copying schema objects
- Ensure configdump output and input config are always saved to robot-save
  even if configdump crashes with assertion failure

11 days ago[Fix] Fix maybe_adjust_type callback return and add nil check
Vsevolod Stakhov [Wed, 19 Nov 2025 11:50:28 +0000 (11:50 +0000)] 
[Fix] Fix maybe_adjust_type callback return and add nil check

Fixed bug where maybe_adjust_type returned only mtype instead of data,mtype
when mtype=='callback'. Added defensive check to prevent passing nil/empty
URL to rspamd_config:add_map which would cause assertion failure.

11 days ago[Rework] Refactor T.transform to validate input first
Vsevolod Stakhov [Wed, 19 Nov 2025 11:26:43 +0000 (11:26 +0000)] 
[Rework] Refactor T.transform to validate input first

Changed T.transform to validate input type before applying transformer.
If transformer returns nil, treat as error. Output is not type-checked.
Updated all usages and tests.

11 days ago[Fix] Fix external_relay mixins and confighelp
Vsevolod Stakhov [Wed, 19 Nov 2025 10:44:27 +0000 (10:44 +0000)] 
[Fix] Fix external_relay mixins and confighelp

- Register external_relay_common mixin for documentation
- Fix confighelp to handle table data (doc objects)

11 days ago[Fix] Fix schema usage in reputation and ratelimit plugins
Vsevolod Stakhov [Wed, 19 Nov 2025 10:41:10 +0000 (10:41 +0000)] 
[Fix] Fix schema usage in reputation and ratelimit plugins

- reputation: use :check() method instead of calling schema as function
- ratelimit: fix burst and rate transform schemas (inner describes result)

11 days ago[Fix] Fix transform schemas - inner schema describes result
Vsevolod Stakhov [Wed, 19 Nov 2025 10:19:09 +0000 (10:19 +0000)] 
[Fix] Fix transform schemas - inner schema describes result

- Transform inner schema now describes the result type, not input
- Fixed lua_maps.lua: timeout transform
- Fixed lua_redis.lua: timeout, sentinel_watch_time, sentinel_master_maxerrors, redis_version
- Fixed rbl.lua: key transforms, return_bits number transforms
- Transform functions now handle type checking before conversion

11 days ago[Fix] Fix RBL plugin transform schemas
Vsevolod Stakhov [Wed, 19 Nov 2025 09:51:20 +0000 (09:51 +0000)] 
[Fix] Fix RBL plugin transform schemas

- Transform inner schema now validates the result, not input
- Updated return_codes_schema and return_bits_schema
- Transform functions now handle type conversion properly

11 days ago[Fix] Improve lua_shape error safety
Vsevolod Stakhov [Wed, 19 Nov 2025 09:17:26 +0000 (09:17 +0000)] 
[Fix] Improve lua_shape error safety

- Transform functions wrapped in pcall to catch user errors
- Default value functions wrapped in pcall
- Pattern matching (string.match, lpeg.match) wrapped in pcall
- Unresolved references return validation errors instead of throwing
- Library now never throws Lua errors on invalid input

11 days ago[Fix] Fix lua_shape transform logic
Vsevolod Stakhov [Wed, 19 Nov 2025 09:06:35 +0000 (09:06 +0000)] 
[Fix] Fix lua_shape transform logic

- Transform now validates original value before transformation
- Open tables now properly apply extra schema with transforms
- Fixes RBL plugin returncodes handling

11 days ago[Fix] Fix external_map_schema call in lua_maps
Vsevolod Stakhov [Tue, 18 Nov 2025 20:24:26 +0000 (20:24 +0000)] 
[Fix] Fix external_map_schema call in lua_maps

12 days ago[Project] Rework mixins and documentation part
Vsevolod Stakhov [Tue, 18 Nov 2025 19:52:08 +0000 (19:52 +0000)] 
[Project] Rework mixins and documentation part

12 days ago[Minor] Add missing
Vsevolod Stakhov [Tue, 18 Nov 2025 14:14:47 +0000 (14:14 +0000)] 
[Minor] Add missing

12 days ago[Project] Use plugins registry
Vsevolod Stakhov [Tue, 18 Nov 2025 14:13:27 +0000 (14:13 +0000)] 
[Project] Use plugins registry

12 days ago[Minor] Update README
Vsevolod Stakhov [Tue, 18 Nov 2025 13:37:46 +0000 (13:37 +0000)] 
[Minor] Update README

12 days ago[Cleanup] Drop tableshape contrib library
Vsevolod Stakhov [Tue, 18 Nov 2025 13:19:15 +0000 (13:19 +0000)] 
[Cleanup] Drop tableshape contrib library

12 days ago[Fix] Fix lua_shape transform compatibility and test issues
Vsevolod Stakhov [Tue, 18 Nov 2025 12:45:29 +0000 (12:45 +0000)] 
[Fix] Fix lua_shape transform compatibility and test issues

Multiple fixes to make lua_shape fully compatible with tableshape:

1. Transform return values: :transform() now returns (value) on success,
   (nil, error) on failure - matching tableshape API. :check() still
   returns (bool, value_or_error).

2. Transform functions: Fix check_transform to pass only value to
   transform function, not (value, ctx). Transform functions expect
   single argument.

3. Test updates: Update all lua_shape unit tests to use new :transform()
   API with (val, err) instead of (ok, val).

4. Selector schema fixes:
   - header: Accept any string for flags, not just literals
   - specific_urls: Simplify boolean+string handling with single transform

All 783 tests now pass: 780 passed, 0 failed, 0 errors, 3 unassertive.

12 days ago[Fix] Make lua_shape :transform() tableshape-compatible
Vsevolod Stakhov [Tue, 18 Nov 2025 12:31:15 +0000 (12:31 +0000)] 
[Fix] Make lua_shape :transform() tableshape-compatible

Change :transform() return values to match tableshape behavior:
- Success: return value (not true, value)
- Failure: return nil, error (not false, error)

This is required for compatibility with lua_selectors check_args which
expects the tableshape return convention. The :check() method still
returns (bool, value_or_error) for new code.

12 days ago[Minor] Migrate lualib/lua_selectors/extractors.lua to lua_shape
Vsevolod Stakhov [Tue, 18 Nov 2025 12:12:35 +0000 (12:12 +0000)] 
[Minor] Migrate lualib/lua_selectors/extractors.lua to lua_shape

Replace tableshape with lua_shape in selector extractors (final migration).

Changes:
- ts.string, ts.number, ts.boolean → T.string(), T.number(), T.boolean()
- ts.array_of(x), ts.one_of({...}) → T.array(x), T.enum({...})
- ts.shape → T.table
- ts.pattern → T.string():with_pattern
- :is_optional() → :optional()

Complex schemas updated including specific_urls with nested options,
url_flags arrays, and header extractors with pattern matching.

12 days ago[Minor] Migrate lualib/lua_selectors/transforms.lua to lua_shape
Vsevolod Stakhov [Tue, 18 Nov 2025 12:11:04 +0000 (12:11 +0000)] 
[Minor] Migrate lualib/lua_selectors/transforms.lua to lua_shape

Replace tableshape with lua_shape in selector transforms.

Changes:
- ts.number + ts.string / fn → T.one_of({T.number(), T.transform(T.string(), fn)})
- ts.string, ts.array_of(x) → T.string(), T.array(x)
- :is_optional() → :optional()

23 transform functions updated with new schema syntax for args_schema.

12 days ago[Minor] Migrate lualib/plugins/rbl.lua to lua_shape
Vsevolod Stakhov [Tue, 18 Nov 2025 12:05:11 +0000 (12:05 +0000)] 
[Minor] Migrate lualib/plugins/rbl.lua to lua_shape

Replace tableshape with lua_shape in RBL plugin utilities.

Changes:
- ts.map_of(k, v) → T.table({}, {open=true, key=..., extra=...})
- ts.shape { ... } → T.table({ ... })
- ts.array_of(x) → T.array(x)
- ts.one_of { ... } → T.enum({ ... })
- ts.boolean, ts.string, ts.number → T.boolean(), T.string(), T.number()
- :is_optional() → :optional()
- Added documentation

Schemas:
- return_codes_schema: Map of symbols to IP patterns
- return_bits_schema: Map of symbols to bit numbers
- rule_schema: Complete RBL rule with 50+ configuration options

12 days ago[Minor] Migrate lualib/plugins/ratelimit.lua to lua_shape
Vsevolod Stakhov [Tue, 18 Nov 2025 12:03:34 +0000 (12:03 +0000)] 
[Minor] Migrate lualib/plugins/ratelimit.lua to lua_shape

Replace tableshape with lua_shape in ratelimit utilities.

Changes:
- ts.shape { ... } → T.table({ ... })
- ts.number + ts.string / fn → T.one_of({T.number(), T.transform(T.string(), fn)})
- :is_optional() → :optional()
- Added comprehensive documentation to all fields

Schema: bucket_schema for ratelimit bucket with burst/rate limits,
optional symbol, message, and skip flags.

12 days ago[Minor] Migrate lualib/lua_selectors/common.lua to lua_shape
Vsevolod Stakhov [Tue, 18 Nov 2025 12:00:58 +0000 (12:00 +0000)] 
[Minor] Migrate lualib/lua_selectors/common.lua to lua_shape

Replace tableshape with lua_shape in selectors common utilities.

Changes:
- ts.one_of { ... } → T.enum({ ... })
- :is_optional() → :optional()
- Added documentation to schema fields

Schema: digest_schema returns array with optional encoding format
and optional hash algorithm for selector digest operations.

12 days ago[Fix] Update lua_mime test to use lua_shape API
Vsevolod Stakhov [Tue, 18 Nov 2025 11:23:10 +0000 (11:23 +0000)] 
[Fix] Update lua_mime test to use lua_shape API

Fix test to use lua_shape's :check() method instead of calling
schema as function (tableshape API).

Change:
- assert_true(schema(ucl_object))
+ local ok, err = schema:check(ucl_object)
+ assert_true(ok, err)

lua_shape schemas cannot be called as functions like tableshape.
They provide :check() and :transform() methods instead.

12 days ago[Feature] Add T.callable() type to lua_shape
Vsevolod Stakhov [Tue, 18 Nov 2025 11:09:22 +0000 (11:09 +0000)] 
[Feature] Add T.callable() type to lua_shape

Add function/callable type validator to lua_shape core.

Implementation:
- check_callable(): Validates value is of type 'function'
- T.callable(opts): Constructor for callable type
- Returns type_mismatch error if value is not a function

This was missing from the initial implementation and is needed by
lua_meta.lua which validates callback functions in metafunction schemas.

Documentation added to README.md scalar types section.

12 days ago[Minor] Migrate src/plugins/lua/reputation.lua to lua_shape
Vsevolod Stakhov [Tue, 18 Nov 2025 10:27:31 +0000 (10:27 +0000)] 
[Minor] Migrate src/plugins/lua/reputation.lua to lua_shape

Replace tableshape with lua_shape in reputation plugin (largest).

Changes:
- ts.shape { ... } → T.table({ ... })
- ts.array_of(x) → T.array(x)
- ts.number + ts.string / fn → T.one_of({T.number(), T.transform(T.string(), fn)})
- ts.one_of(a, b) → T.one_of({named variants})
- :is_optional() → :optional()
- Uses lua_redis.enrich_schema for Redis backend
- Added comprehensive documentation to all fields

Schemas:
- generic_selector: selector-based reputation with whitelist/exclusion
- redis backend: prefix, expiry, and time buckets array
- dns backend: simple DNS list configuration

12 days ago[Minor] Migrate src/plugins/lua/neural.lua to lua_shape
Vsevolod Stakhov [Tue, 18 Nov 2025 10:25:33 +0000 (10:25 +0000)] 
[Minor] Migrate src/plugins/lua/neural.lua to lua_shape

Replace tableshape with lua_shape in neural plugin.

Changes:
- ts.shape { ... } → T.table({ ... })
- ts.string, ts.number → T.string(), T.number()
- ts.array_of(x) → T.array(x)
- :is_optional() → :optional()
- Added comprehensive documentation to all fields

Schema: redis_profile_schema for neural network profiles stored in
Redis, including digest, symbols, version, and optional distance.

12 days ago[Minor] Migrate src/plugins/lua/milter_headers.lua to lua_shape
Vsevolod Stakhov [Tue, 18 Nov 2025 10:15:14 +0000 (10:15 +0000)] 
[Minor] Migrate src/plugins/lua/milter_headers.lua to lua_shape

Replace tableshape with lua_shape in milter_headers plugin.

Changes:
- ts.shape({...}) → T.table({...})
- ts.array_of(x) → T.array(x)
- ts.string + ts.string / fn → T.one_of({T.array(), T.transform(T.string(), fn)})
- ts.map_of(k, v) → T.table({}, {open=true, extra=v})
- :is_optional() → :optional()
- extra_fields option → open=true table option
- Added comprehensive documentation to all fields

Schema: config_schema with flexible 'use' field accepting string or
array, optional flags, header lists, map schema, and custom headers.

12 days ago[Minor] Migrate rules/controller/neural.lua to lua_shape
Vsevolod Stakhov [Tue, 18 Nov 2025 10:13:45 +0000 (10:13 +0000)] 
[Minor] Migrate rules/controller/neural.lua to lua_shape

Replace tableshape with lua_shape in neural controller.

Changes:
- ts.shape { ... } → T.table({ ... })
- ts.array_of(ts.array_of(x)) → T.array(T.array(x))
- ts.string, ts.number → T.string(), T.number()
- :is_optional() → :optional()
- Added comprehensive documentation to all fields

Schema: learn_request_schema for neural network training requests
with nested arrays for ham and spam training vectors.

12 days ago[Minor] Migrate src/plugins/lua/bimi.lua to lua_shape
Vsevolod Stakhov [Tue, 18 Nov 2025 10:07:51 +0000 (10:07 +0000)] 
[Minor] Migrate src/plugins/lua/bimi.lua to lua_shape

Replace tableshape with lua_shape in BIMI plugin.

Changes:
- Uses lua_redis.enrich_schema() which returns lua_shape with mixins
- ts.string, ts.boolean, ts.number → T.string(), T.boolean(), T.number()
- ts.number + ts.string / fn → T.one_of({T.number(), T.transform(T.string(), fn)})
- :is_optional() → :optional()
- Added comprehensive documentation to all fields

Schema: settings_schema with Redis common fields plus BIMI-specific
settings for helper service URL, timeouts, VMC-only mode, and staged
HTTP timeouts (connect, SSL, write, read).

12 days ago[Minor] Migrate src/plugins/lua/contextal.lua to lua_shape
Vsevolod Stakhov [Tue, 18 Nov 2025 10:01:44 +0000 (10:01 +0000)] 
[Minor] Migrate src/plugins/lua/contextal.lua to lua_shape

Replace tableshape with lua_shape in Contextal plugin.

Changes:
- Uses lua_redis.enrich_schema() which returns lua_shape with mixins
- ts.string, ts.boolean, ts.number → T.string(), T.boolean(), T.number()
- ts.array_of(x) → T.array(x)
- :is_optional() → :optional()
- Added comprehensive documentation to all fields

Schema: config_schema with Redis common fields plus Contextal-specific
settings for API URLs, caching, timeouts, and custom actions.

12 days ago[Minor] Migrate src/plugins/lua/clustering.lua to lua_shape
Vsevolod Stakhov [Tue, 18 Nov 2025 09:55:40 +0000 (09:55 +0000)] 
[Minor] Migrate src/plugins/lua/clustering.lua to lua_shape

Replace tableshape with lua_shape in clustering plugin.

Changes:
- ts.shape { ... } → T.table({ ... })
- ts.number, ts.string → T.number(), T.string()
- ts.number + ts.string / fn → T.one_of({T.number(), T.transform(T.string(), fn)})
- :is_optional() → :optional()
- Added comprehensive documentation to all fields

Schema: rule_schema with clustering configuration including max_elts,
expire times, score multipliers for spam/junk/ham, and selectors.

12 days ago[Minor] Migrate src/plugins/lua/history_redis.lua to lua_shape
Vsevolod Stakhov [Tue, 18 Nov 2025 09:54:34 +0000 (09:54 +0000)] 
[Minor] Migrate src/plugins/lua/history_redis.lua to lua_shape

Replace tableshape with lua_shape in history_redis plugin.

Changes:
- Uses lua_redis.enrich_schema() which now returns lua_shape with mixins
- ts.string, ts.boolean, ts.number → T.string(), T.boolean(), T.number()
- ts.number + ts.string / fn → T.one_of({T.number(), T.transform(T.string(), fn)})
- :is_optional() → :optional()
- Added comprehensive documentation to all fields

Schema: settings_schema with Redis common fields (via mixin) plus
history-specific fields like key_prefix, nrows, compress, and
subject privacy options.

12 days ago[Minor] Migrate src/plugins/lua/external_relay.lua to lua_shape
Vsevolod Stakhov [Tue, 18 Nov 2025 09:33:57 +0000 (09:33 +0000)] 
[Minor] Migrate src/plugins/lua/external_relay.lua to lua_shape

Replace tableshape with lua_shape in external relay plugin.

Changes:
- ts.shape { ... } → T.table({ ... })
- ts.map_of(ts.string, schema) → T.table({}, {open=true, extra=schema})
- ts.one_of with 5 strategy variants → T.one_of with named variants
- Created rule_common mixin for priority/symbol fields
- All 5 strategy variants (authenticated, count, local, hostname_map,
  ip_map) use mixin for common fields
- Added comprehensive documentation

Schema: config_schema with rules map where each value is one of 5
strategy types, using mixins for field origin tracking.

12 days ago[Minor] Migrate src/plugins/lua/aws_s3.lua to lua_shape
Vsevolod Stakhov [Tue, 18 Nov 2025 09:28:00 +0000 (09:28 +0000)] 
[Minor] Migrate src/plugins/lua/aws_s3.lua to lua_shape

Replace tableshape with lua_shape in AWS S3 plugin.

Changes:
- ts.shape { ... } → T.table({ ... })
- ts.string, ts.boolean, ts.number → T.string(), T.boolean(), T.number()
- ts.number + ts.string / fn → T.one_of({T.number(), T.transform(T.string(), fn)})
- :is_optional() → :optional()
- Added comprehensive documentation to all fields

Schema: settings_schema for AWS S3 configuration including bucket,
region, credentials, timeout, compression, and content options.

12 days ago[Minor] Migrate rules/controller/maps.lua to lua_shape
Vsevolod Stakhov [Tue, 18 Nov 2025 09:22:35 +0000 (09:22 +0000)] 
[Minor] Migrate rules/controller/maps.lua to lua_shape

Replace tableshape with lua_shape in controller maps plugin.

Changes:
- ts.shape { ... } → T.table({ ... })
- ts.array_of(x) → T.array(x)
- :is_optional() → :optional()
- Added documentation to all fields and schema

Schema: query_json_schema for validating map query requests
with optional maps filter and report_misses flag.

12 days ago[Feature] Add callable defaults support to lua_shape
Vsevolod Stakhov [Mon, 17 Nov 2025 21:31:55 +0000 (21:31 +0000)] 
[Feature] Add callable defaults support to lua_shape

Enhance lua_shape to support function values as defaults that are
evaluated dynamically at validation time, not at schema definition time.

Core changes:
- check_optional(): Check if default is a function and call it
- check_table(): Same for table field defaults
- Enables patterns like: T.string():with_default(get_timestamp)

lua_aws.lua cleanup:
Replace ugly patterns like:
  T.transform(T.one_of({T.string(), T.literal(nil)}),
    function(v) return v or 'GET' end)
With clean:
  T.string():with_default('GET')

For dynamic defaults (date field), use:
  T.string():with_default(today_canonical)  -- function ref, not call

Benefits:
- Much cleaner and more readable schemas
- Consistent with lua_shape design philosophy
- Dynamic defaults for timestamps, random values, etc.
- Static defaults for constants

All tests pass (44/44).

12 days ago[Minor] Remove testing section from lua_shape README
Vsevolod Stakhov [Mon, 17 Nov 2025 21:27:20 +0000 (21:27 +0000)] 
[Minor] Remove testing section from lua_shape README

Remove references to non-existent test files in repository root.
Tests are properly located in test/lua/unit/lua_shape.lua.

12 days ago[Minor] Migrate lua_redis.lua to lua_shape with mixin tracking
Vsevolod Stakhov [Mon, 17 Nov 2025 21:12:29 +0000 (21:12 +0000)] 
[Minor] Migrate lua_redis.lua to lua_shape with mixin tracking

Replace tableshape with lua_shape using first-class mixin system
to preserve origin tracking for documentation and better error reporting.

Key changes:
- common_schema: Now a proper T.table() schema (not plain table)
- Schema composition: Uses T.mixin() instead of lutil.table_merge()
- enrich_schema: Returns T.one_of() with 6 named variants, each using
  mixins for redis_common and external fields
- All tables use { open = true } to allow additional fields
- Transform patterns: T.transform(T.number(), tostring) for type conversions
- Union types: T.one_of({...}) for alternatives like string | array

Benefits:
- Mixin origin tracking preserved in field metadata
- Documentation generation can show field sources
- Better error messages with mixin context
- Consistent with lua_shape design philosophy

13 days ago[Minor] Migrate lua_mime.lua from tableshape to lua_shape
Vsevolod Stakhov [Mon, 17 Nov 2025 18:07:34 +0000 (18:07 +0000)] 
[Minor] Migrate lua_mime.lua from tableshape to lua_shape

Replace tableshape with lua_shape in message_to_ucl_schema function:
- Convert ts.shape to T.table
- Convert :describe() to :doc({ summary = ... })
- Convert :is_optional() to :optional()
- Convert ts.array_of to T.array
- Convert ts.pattern to T.string({ pattern = ... })
- Convert ts.one_of to T.enum for simple value lists
- Convert ts.integer/string/boolean to T.integer()/string()/boolean()

Transforms nested schemas: headers_schema, part_schema, email_addr_schema,
envelope_schema. No functional changes, luacheck passes.

13 days ago[Minor] Migrate lua_meta.lua from tableshape to lua_shape
Vsevolod Stakhov [Mon, 17 Nov 2025 16:46:46 +0000 (16:46 +0000)] 
[Minor] Migrate lua_meta.lua from tableshape to lua_shape

Replace tableshape with lua_shape for metafunction schema:
- Convert ts.shape to T.table
- Convert ts.func to T.callable()
- Convert ts.array_of to T.array
- Convert :is_optional() to :optional()

No functional changes, luacheck passes.

13 days ago[Minor] Migrate lua_maps.lua from tableshape to lua_shape
Vsevolod Stakhov [Mon, 17 Nov 2025 16:32:01 +0000 (16:32 +0000)] 
[Minor] Migrate lua_maps.lua from tableshape to lua_shape

Replace tableshape with lua_shape for map configuration schemas:
- Convert ts.shape to T.table
- Convert ts.equivalent(true) to T.literal(true)
- Convert :is_optional() to :optional()
- Convert ts.one_of to T.one_of with proper braces
- Convert ts.enum with :is_optional() to T.enum():optional()
- Convert ts.array_of to T.array

Updates external_map_schema, direct_map_schema, and exports.map_schema.
No functional changes, luacheck passes.

13 days ago[Minor] Migrate lua_fuzzy.lua from tableshape to lua_shape
Vsevolod Stakhov [Mon, 17 Nov 2025 15:32:50 +0000 (15:32 +0000)] 
[Minor] Migrate lua_fuzzy.lua from tableshape to lua_shape

Replace tableshape with lua_shape for fuzzy policy schemas:
- Convert ts.number + ts.string / tonumber to T.transform + T.one_of
- Convert ts.array_of to T.array
- Convert ts.boolean to T.boolean()
- Convert ts.shape to T.table with open option support

No functional changes, luacheck passes.

13 days ago[Minor] Migrate lua_maps_expressions.lua from tableshape to lua_shape
Vsevolod Stakhov [Mon, 17 Nov 2025 15:31:52 +0000 (15:31 +0000)] 
[Minor] Migrate lua_maps_expressions.lua from tableshape to lua_shape

Replace tableshape with lua_shape for maps expressions schema:
- Convert ts.shape to T.table
- Convert ts.array_of to T.array
- Keep reference to lua_maps.map_schema (will be migrated separately)

No functional changes, luacheck passes.

13 days ago[Minor] Migrate lua_aws.lua from tableshape to lua_shape
Vsevolod Stakhov [Mon, 17 Nov 2025 15:29:36 +0000 (15:29 +0000)] 
[Minor] Migrate lua_aws.lua from tableshape to lua_shape

Replace tableshape with lua_shape for AWS parameter validation:
- Convert ts.shape to T.table
- Replace ts.string + ts['nil'] / fn with T.transform + T.one_of
- Replace ts.map_of(ts.string, ts.string) with open table validation
- Update documentation comments to reflect new schema format

No functional changes, luacheck passes.

13 days ago[Feature] Add lua_shape validation library as tableshape replacement
Vsevolod Stakhov [Mon, 17 Nov 2025 14:43:36 +0000 (14:43 +0000)] 
[Feature] Add lua_shape validation library as tableshape replacement

Implement comprehensive schema validation library with improved features:

* Better one_of error reporting with intersection analysis
* Schema-driven documentation generation with mixin tracking
* Rich type constraints (ranges, lengths, Lua patterns)
* First-class mixins with origin tracking for composition
* JSON Schema Draft 7 export for UCL validation
* Transform support with immutable semantics
* Pure Lua implementation with optional lpeg support

The library provides 4 core modules:
- core.lua: All type constructors, validation, and utilities
- registry.lua: Schema registration and reference resolution
- jsonschema.lua: JSON Schema export
- docs.lua: Documentation IR generation

Includes comprehensive test suite (44 tests, 119 assertions).
Designed to gradually replace tableshape across 22 modules.

2 weeks agoMerge pull request #5744 from dragoangel/patch-15
Vsevolod Stakhov [Sun, 16 Nov 2025 15:14:51 +0000 (15:14 +0000)] 
Merge pull request #5744 from dragoangel/patch-15

chore: add missing semicolon in whitelist.conf

2 weeks agoMerge pull request #5748 from rspamd/vstakhov-url-deep-processing
Vsevolod Stakhov [Sat, 15 Nov 2025 20:38:17 +0000 (20:38 +0000)] 
Merge pull request #5748 from rspamd/vstakhov-url-deep-processing

[Feature] URL deep processing architecture

2 weeks ago[Fix] Encode redirect URLs to handle unencoded spaces and special characters 5748/head
Vsevolod Stakhov [Sat, 15 Nov 2025 15:53:17 +0000 (15:53 +0000)] 
[Fix] Encode redirect URLs to handle unencoded spaces and special characters

This fixes issue #5525 where url_redirector fails when redirect Location
headers contain unencoded spaces or other special characters.

The http_parser_parse_url() function strictly requires percent-encoded URLs
per RFC 3986, but many servers send Location headers with unencoded spaces.

Changes:
- Add encode_url_for_redirect() function to percent-encode problematic characters
- Apply encoding to redirect Location headers before creating URL objects
- Preserve already-encoded sequences (no double-encoding)
- Log warnings for URLs that fail even after encoding

The fix is conservative - only encodes characters that http_parser rejects,
maintaining full backward compatibility with properly formatted URLs.

Closes: #5525
2 weeks ago[Minor] Address review thingies (mostly fp though)
Vsevolod Stakhov [Sat, 15 Nov 2025 15:33:22 +0000 (15:33 +0000)] 
[Minor] Address review thingies (mostly fp though)

2 weeks ago[Fix] Fix tests failures
Vsevolod Stakhov [Sat, 15 Nov 2025 14:30:50 +0000 (14:30 +0000)] 
[Fix] Fix tests failures

2 weeks ago[Fix] Fix strings processing
Vsevolod Stakhov [Sat, 15 Nov 2025 13:54:49 +0000 (13:54 +0000)] 
[Fix] Fix strings processing

2 weeks ago[Fix] Rewrite lua_url_filter using available Lua string functions
Vsevolod Stakhov [Sat, 15 Nov 2025 11:01:18 +0000 (11:01 +0000)] 
[Fix] Rewrite lua_url_filter using available Lua string functions

- Pass URL as rspamd_text from C (for future optimizations)
- Convert to string in Lua (acceptable - called rarely on suspicious patterns)
- Use string.find() with string.char() for control character detection
- Use string.gsub() trick for counting @ signs
- Avoid non-existent memchr() method (not implemented for rspamd_text)
- Clean, simple implementation using standard Lua functions

Performance:
- Called only when C parser encounters suspicious patterns
- Conversion overhead acceptable given low frequency
- Future: can optimize with proper memspn functions if needed

Fixes:
- Runtime error: attempt to call method 'memchr' (a nil value)
- Luacheck warning: empty if branch

2 weeks ago[Test] Add comprehensive tests for URL deep processing
Vsevolod Stakhov [Sat, 15 Nov 2025 09:49:22 +0000 (09:49 +0000)] 
[Test] Add comprehensive tests for URL deep processing

Unit tests (test/lua/unit/lua_url_filter.lua):
- filter_url_string basic validation (normal, long user, multiple @)
- filter_url with URL objects
- UTF-8 validation (ASCII, Cyrillic, Japanese, invalid)
- Custom filter registration and chaining
- Issue #5731 regression test (oversized user parsing)

Functional tests (test/functional/cases/001_merged/400_url_suspect.robot):
- Moved to 001_merged for shared setup/teardown
- Long user field (80 chars) - URL_USER_LONG
- Very long user field (300 chars) - URL_USER_VERY_LONG
- Numeric IP - URL_NUMERIC_IP
- Numeric IP with user - URL_NUMERIC_IP_USER
- Suspicious TLD - URL_SUSPICIOUS_TLD
- Multiple @ signs - URL_MULTIPLE_AT_SIGNS
- Normal URLs (no false positives)
- All tests verify R_SUSPICIOUS_URL backward compatibility

Test messages (test/functional/messages/):
- url_suspect_long_user.eml (80-char user)
- url_suspect_very_long_user.eml (300-char user)
- url_suspect_numeric_ip.eml
- url_suspect_numeric_ip_user.eml
- url_suspect_bad_tld.eml
- url_suspect_multiple_at.eml
- url_suspect_normal.eml

Config:
- Enable url_suspect plugin in merged-override.conf
- Add Robot Framework outputs to gitignore

2 weeks ago[Fix] Remove shadowing of rspamd_logger in rules/misc.lua
Vsevolod Stakhov [Fri, 14 Nov 2025 20:57:01 +0000 (20:57 +0000)] 
[Fix] Remove shadowing of rspamd_logger in rules/misc.lua

- Fixes luacheck W431 warning (shadowing upvalue)
- rspamd_logger already required at module level (line 24)
- Remove redundant local require inside function

2 weeks ago[Fix] Complete lua_State parameter threading through codebase
Vsevolod Stakhov [Fri, 14 Nov 2025 20:21:29 +0000 (20:21 +0000)] 
[Fix] Complete lua_State parameter threading through codebase

- Add forward declaration in url.c for rspamd_url_lua_consult
- Add lua_State forward declaration in html_url.hxx
- Add lua_State parameter to html_append_tag_content
- Add lua_State parameter to html_process_img_tag
- Add lua_State parameter to html_process_link_tag
- Add lua_State parameter to html_url_is_phished
- Cast void* to lua_State* when calling HTML functions from task context
- Cast lua_State* to void* when calling C API from C++ functions
- All compilation errors resolved
- Build successful

2 weeks ago[Fix] Update all rspamd_url_find_multiple callers with lua_state
Vsevolod Stakhov [Fri, 14 Nov 2025 20:09:50 +0000 (20:09 +0000)] 
[Fix] Update all rspamd_url_find_multiple callers with lua_state

- Add lua_state parameter to lua_task.c (inject_url_query_callback)
- Add lua_state parameter to message.c (Subject header URL extraction)
- Add lua_state parameter to lua_url.c (rspamd.url.all function)
- All callers pass task->cfg->lua_state or L depending on context
- Completes the lua_state parameter addition

2 weeks ago[Fix] Use void* for lua_state in public API
Vsevolod Stakhov [Fri, 14 Nov 2025 20:06:39 +0000 (20:06 +0000)] 
[Fix] Use void* for lua_state in public API

- Change lua_State* to void* in url.h public functions
- Fixes C compilation: struct lua_State and lua_State are distinct types in C
- Cast void* to lua_State* inside implementation (url.c)
- Updated: rspamd_url_parse(), rspamd_url_find_multiple()
- Updated: rspamd_web_parse() internal function
- Updated: url_callback_data structure
- Follows C convention: opaque pointers in public headers

2 weeks ago[Fix] Add missing rspamd_logger require in rules/misc.lua
Vsevolod Stakhov [Fri, 14 Nov 2025 19:57:15 +0000 (19:57 +0000)] 
[Fix] Add missing rspamd_logger require in rules/misc.lua

- Fixes luacheck warning W113 (accessing undefined variable)
- rspamd_logger used in conditional registration logic

2 weeks ago[Fix] Add forward declaration for lua_State in url.h
Vsevolod Stakhov [Fri, 14 Nov 2025 19:24:26 +0000 (19:24 +0000)] 
[Fix] Add forward declaration for lua_State in url.h

- Add 'struct lua_State;' forward declaration
- Fixes compilation errors in C files that include url.h but not lua.h
- Follows Rspamd convention (same pattern as other headers)

2 weeks ago[Feature] Pass lua_State through HTML URL processing
Vsevolod Stakhov [Fri, 14 Nov 2025 18:18:32 +0000 (18:18 +0000)] 
[Feature] Pass lua_State through HTML URL processing

- Add lua_State parameter to html_process_url() and html_process_url_tag()
- Add lua_State parameter to html_check_displayed_url() and html_process_displayed_href_tag()
- Add lua_State parameter to html_process_query_url()
- Pass task->cfg->lua_state from html_process_input() to all URL processing functions
- All rspamd_url_parse() calls in HTML now have proper lua_State
- HTML URL processing now benefits from Lua filter consultation
- Completes lua_State plumbing - now universally available throughout URL processing chain

2 weeks ago[Refactor] Use enum and pass lua_State through url_callback_data
Vsevolod Stakhov [Fri, 14 Nov 2025 18:07:46 +0000 (18:07 +0000)] 
[Refactor] Use enum and pass lua_State through url_callback_data

- Add enum rspamd_url_lua_filter_result for return values (ACCEPT/SUSPICIOUS/REJECT)
- Replace magic numbers (0/1/2) with enum constants throughout
- Add lua_state field to struct url_callback_data
- Pass lua_State through rspamd_url_find_multiple() chain
- Update all callers: task contexts pass task->cfg->lua_state, others pass NULL
- rspamd_url_trie_generic_callback_common now uses cb->lua_state
- More idiomatic C code with proper type safety
- lua_State now universally available where URL parsing happens

2 weeks ago[Feature] Wire C->Lua URL filter consultation through parser
Vsevolod Stakhov [Fri, 14 Nov 2025 18:04:08 +0000 (18:04 +0000)] 
[Feature] Wire C->Lua URL filter consultation through parser

- Add lua_State parameter to rspamd_url_parse() and rspamd_web_parse()
- Pass lua_State through entire parsing chain
- Call rspamd_url_lua_consult() at two critical points:
  * Oversized user field (>max_email_user) - line 1205
  * Multiple @ signs detected - line 1227
- Lua filter can now REJECT (abort), SUSPICIOUS (mark obscured), or ACCEPT
- Update all callers: pass task->cfg->lua_state when available, NULL otherwise
- HTML parser calls: pass NULL (no task context)
- URL extraction: pass NULL (callback data doesn't have task)
- Query URL parsing: pass task->cfg->lua_state (has task context)
- Completes two-level architecture: C consults Lua on ambiguous patterns

2 weeks ago[Feature] Add C->Lua URL filter consultation infrastructure
Vsevolod Stakhov [Fri, 14 Nov 2025 17:18:37 +0000 (17:18 +0000)] 
[Feature] Add C->Lua URL filter consultation infrastructure

- Add rspamd_url_lua_consult() helper function in url.c
- Function calls lua_url_filter.filter_url_string() from C
- Returns ACCEPT/SUSPICIOUS/REJECT to guide C parser
- Add filter_url_string() function in lua_url_filter.lua
- Validates URL strings and rejects obvious garbage
- Checks: length, @ count, user field size, control chars, UTF-8
- Add TODO comment at oversized user field check (line 1204)
- Infrastructure ready, needs lua_State plumbing through call chain
- This completes the two-level architecture design

2 weeks ago[Fix] Update config comments to guide users to local.d
Vsevolod Stakhov [Fri, 14 Nov 2025 14:06:37 +0000 (14:06 +0000)] 
[Fix] Update config comments to guide users to local.d

- Changed comments from 'Uncomment to enable' to 'To enable, add in local.d/url_suspect.conf:'
- Users should not edit shipped config files directly
- Follow Rspamd convention: use local.d/override.d for user customizations
- Updated all map parameter comments for consistency
- Clearer path structure: use local.d/maps/ subdirectory

2 weeks ago[Refactor] Simplify configuration by removing use_*_map flags
Vsevolod Stakhov [Fri, 14 Nov 2025 13:56:39 +0000 (13:56 +0000)] 
[Refactor] Simplify configuration by removing use_*_map flags

- Removed all use_pattern_map, use_range_map, use_tld_map, etc. flags
- Maps are now implicitly enabled if configured (not nil)
- Cleaner configuration: just uncomment the map parameter to enable
- Updated init_maps() to check map existence instead of enable flags
- Updated check functions to use maps if configured
- Simpler, more intuitive configuration approach

2 weeks ago[Cleanup] Remove example maps and add doc/ to gitignore
Vsevolod Stakhov [Fri, 14 Nov 2025 13:42:06 +0000 (13:42 +0000)] 
[Cleanup] Remove example maps and add doc/ to gitignore

- Removed example map files from conf/maps.d/url_suspect/
- Added doc/ to .gitignore for transient documentation
- Added conf/maps.d/url_suspect/ to .gitignore for user-created maps
- Example maps and documentation belong in separate docs repository
- Users can create their own maps in conf/maps.d/url_suspect/ as needed

2 weeks ago[Fix] Avoid duplicate R_SUSPICIOUS_URL symbol registration
Vsevolod Stakhov [Fri, 14 Nov 2025 13:34:38 +0000 (13:34 +0000)] 
[Fix] Avoid duplicate R_SUSPICIOUS_URL symbol registration

When url_suspect plugin is enabled, skip the old R_SUSPICIOUS_URL
registration in rules/misc.lua to avoid symbol duplication.

The old implementation is kept for backward compatibility when the
new plugin is disabled.

2 weeks ago[Feature] Add URL deep processing architecture
Vsevolod Stakhov [Fri, 14 Nov 2025 12:27:21 +0000 (12:27 +0000)] 
[Feature] Add URL deep processing architecture

This commit implements a two-level URL processing system that addresses
issue #5731 and provides flexible URL analysis with multiple specific symbols.

Core changes:
* Modified src/libserver/url.c to handle oversized user fields (fixes #5731)
* Added lualib/lua_url_filter.lua - Fast library filter during parsing
* Added src/plugins/lua/url_suspect.lua - Deep inspection plugin
* Added conf/modules.d/url_suspect.conf - Plugin configuration
* Added conf/scores.d/url_suspect_group.conf - Symbol scores

Key features:
* No new C flags - uses existing URL flags (has_user, numeric, obscured, etc.)
* Works without maps - built-in logic for common cases
* 15+ specific symbols instead of generic R_SUSPICIOUS_URL
* Backward compatible - keeps R_SUSPICIOUS_URL working
* User extensible - custom filters and checks supported

Optional features:
* Example map files for advanced customization (disabled by default)
* Whitelist, pattern matching, TLD lists

Issue: #5731

2 weeks agoMerge pull request #5746 from fatalbanana/whitelist_maps
Vsevolod Stakhov [Fri, 14 Nov 2025 11:00:39 +0000 (11:00 +0000)] 
Merge pull request #5746 from fatalbanana/whitelist_maps

[Minor] whitelist: use contemporary API for maps

2 weeks ago[Minor] whitelist: use contemporary API for maps 5746/head
Andrew Lewis [Fri, 14 Nov 2025 10:24:49 +0000 (12:24 +0200)] 
[Minor] whitelist: use contemporary API for maps

2 weeks agochore: add missing semicolon in whitelist.conf 5744/head
Dmitriy Alekseev [Thu, 13 Nov 2025 13:12:08 +0000 (14:12 +0100)] 
chore: add missing semicolon in whitelist.conf

2 weeks ago[Minor] Update version to 3.14.1
Vsevolod Stakhov [Thu, 13 Nov 2025 09:08:11 +0000 (09:08 +0000)] 
[Minor] Update version to 3.14.1

2 weeks agoMerge pull request #5741 from moisseev/webui
Vsevolod Stakhov [Wed, 12 Nov 2025 22:22:24 +0000 (22:22 +0000)] 
Merge pull request #5741 from moisseev/webui

[Minor] Fix hover behavior for Status tab tables

2 weeks ago[Minor] Improve droid code review workflow: use Sonnet, add explicit completion comme...
Vsevolod Stakhov [Wed, 12 Nov 2025 11:27:23 +0000 (11:27 +0000)] 
[Minor] Improve droid code review workflow: use Sonnet, add explicit completion comment, dismiss old change requests

2 weeks ago[Fix] Keep groups_*/symbols_* fields in settings for runtime processing
Vsevolod Stakhov [Wed, 12 Nov 2025 10:25:05 +0000 (10:25 +0000)] 
[Fix] Keep groups_*/symbols_* fields in settings for runtime processing

The Lua settings preprocessing was removing groups_disabled, groups_enabled,
symbols_disabled, and symbols_enabled fields from settings objects after
converting them to individual symbol lists. However, the C++ runtime code
(rspamd_symcache_process_settings) also needs these fields to mark symbols
as enabled/disabled in the runtime state.

Background:
- June 2019: Lua preprocessing added, removed fields to 'avoid clash'
- April 2022: C++ runtime process_settings() added, which reads these fields
- The two mechanisms were never properly synchronized

How settings work:
1. Lua preprocessing (at config load): Converts groups_* to symbol lists,
   registers via rspamd_config:register_settings_id(), creates settings_elt
   with allowed/forbidden symbol IDs for enforcement
2. C++ runtime (when settings applied): Reads task->settings UCL object,
   processes groups_*/symbols_* fields to mark symbols as finished/not_started
   in the runtime state for optimization

The issue:
When settings are applied via task:set_settings(cached.settings.apply),
the Lua table is converted to UCL and stored in task->settings. If the
groups_* fields were removed by preprocessing, process_settings() cannot
find them, so symbols don't get marked as disabled in runtime state.

The fix:
Don't remove these fields. Both mechanisms work complementarily:
- Settings element: Enforcement (checks allowed/forbidden IDs per symbol)
- Runtime processing: Optimization (marks symbols as finished to skip them)

This is safe because:
- The preprocessing still builds correct allowed/forbidden symbol lists
- The runtime processing reads the same fields and applies them correctly
- No conflict occurs - they work on different aspects (enforcement vs state)

Note: This affects settings IDs (static settings), not dynamic settings
applied directly via Settings={} header, which never went through the
removal step.

2 weeks ago[Minor] Improve droid code review workflow to prevent repeated feedback and test...
Vsevolod Stakhov [Wed, 12 Nov 2025 08:59:26 +0000 (08:59 +0000)] 
[Minor] Improve droid code review workflow to prevent repeated feedback and test comments

2 weeks agoMerge pull request #5742 from moisseev/hover
Vsevolod Stakhov [Tue, 11 Nov 2025 20:55:41 +0000 (20:55 +0000)] 
Merge pull request #5742 from moisseev/hover

[Minor] WebUI: Restore hover colors for symbols

2 weeks ago[Minor] WebUI: Restore hover colors for symbols 5742/head
Alexander Moisseev [Tue, 11 Nov 2025 17:47:18 +0000 (20:47 +0300)] 
[Minor] WebUI: Restore hover colors for symbols

Fix regression introduced in #5725 where symbol hover states were
unified to a single color, losing the visual distinction between symbol types.

2 weeks ago[Minor] Restore symbol hover outside status tables 5741/head
Alexander Moisseev [Tue, 11 Nov 2025 14:54:46 +0000 (17:54 +0300)] 
[Minor] Restore symbol hover outside status tables

2 weeks ago[Minor] Fix hover behavior for Status tab tables
Alexander Moisseev [Tue, 11 Nov 2025 13:32:10 +0000 (16:32 +0300)] 
[Minor] Fix hover behavior for Status tab tables

Tables with rowspan cells (Bayesian statistics and Fuzzy hashes)
now have consistent hover highlighting across all rows in a group.

2 weeks agoRelease 3.14.0 3.14.0
Vsevolod Stakhov [Mon, 10 Nov 2025 15:54:44 +0000 (15:54 +0000)] 
Release 3.14.0

* [Feature] Fuzzy check: Add HTML fuzzy hashing for structural similarity matching
* [Feature] Fuzzy check: Add per-rule text_hashes toggle for HTML-only fuzzy rules
* [Feature] Fuzzy check: Add structured checks configuration with backward compatibility
* [Feature] Fuzzy storage: Implement full TCP protocol support with auto-switch
* [Feature] Fuzzy check: Add TCP connection management and error handling
* [Feature] URL: Add task:get_cta_urls() API for proper CTA domain extraction
* [Feature] URL: Move CTA processing into dedicated module
* [Feature] URL: Add url:get_hash() method for efficient deduplication without string conversion
* [Feature] GPT: Add web search context support with Redis caching
* [Feature] HTML: Add infrastructure for async URL rewriting with Lua bindings
* [Feature] HTML: Add task:rewrite_html_urls() and task:get_html_urls() Lua API
* [Feature] WebUI: Implement dark mode with theme toggle and auto detection
* [Feature] Aliases: Add advanced resolution with loop detection for converging paths
* [Feature] Milter: Add ESMTP argument parsing with Lua API access
* [Feature] Milter: Add per-recipient ESMTP args parsing and metadata access
* [Feature] Milter: Support array of positions for remove_headers operations
* [Feature] Proxy: Add client IP preservation in message headers through chain
* [Feature] Rspamc: Add milter.add_headers object format support to --mime
* [Feature] Configwizard: Add Postfix integration wizard using postconf utility
* [Feature] Build: Add comprehensive BSD workflows (FreeBSD, NetBSD, OpenBSD) with Lua version selection
* [Feature] Build: Add automated code review GitHub Actions workflow with Rspamd-specific guidelines
* [Feature] Build: Add Docker-based integration test suite with ASAN and real corpus
* [Feature] Build: Add automatic public suffix list synchronization
* [Feature] Multimap: Add support for symbols with leading numerals
* [Feature] DMARC: Add Auto-Reply-To and Precedence headers to prevent out-of-office replies
* [Feature] Platform: Add NetBSD memory usage tracking support
* [Feature] Utilities: Add fuzzy Redis migration utility
* [Feature] Bayes: Allow skipping local/authenticated mail in autolearn condition
* [Feature] ARC: Add DKIM signing key API for flexible ARC signing
* [Feature] Logger: Add type specifiers support for better formatting
* [Feature] Heap: Add rspamd_heap_push_slot to eliminate double allocation
* [Fix] DNS: Preserve req->pos during reply validation to prevent packet truncation on UDP-to-TCP retransmits
* [Fix] DNS: Regenerate transaction ID before copying to TCP buffer to avoid collisions
* [Fix] DNS: Fix nameserver round-robin when using /etc/resolv.conf
* [Fix] DNS: Fix TCP uninitialized memory leak
* [Fix] DMARC: Add batching and forced GC for Redis connections to prevent pool exhaustion
* [Fix] DMARC: Validate and normalize batch_size to prevent fractional indexing and loop errors
* [Fix] DMARC: Refactor reporting to use helper functions and async maps
* [Fix] Allocator: Fix jemalloc/system malloc mixing in getline() to prevent crashes
* [Fix] Allocator: Fix allocator mismatches in hiredis
* [Fix] Allocator: Fix allocator mismatches in libucl
* [Fix] Hyperscan: Use runtime version instead of compile-time for database validation
* [Fix] Hyperscan: Auto-recreate invalid unserialized cache files on version mismatch
* [Fix] Memory: Fix leaks in fuzzy storage khash tables
* [Fix] Memory: Fix leaks in upstream address parsing
* [Fix] Memory: Fix leaks in *-any address parsing
* [Fix] Memory: Fix OpenSSL providers cleanup
* [Fix] Memory: Fix UCL object memory leak in Lua integration
* [Fix] Memory: Fix stat metadata tokenization leak
* [Fix] Fuzzy TCP: Fix double-release in fuzzy_tcp_session
* [Fix] Fuzzy TCP: Fix refcount leak in destructor
* [Fix] Fuzzy TCP: Fix timeout handling and buffer overflow
* [Fix] Fuzzy TCP: Fix endianness mismatch in framing protocol
* [Fix] Fuzzy TCP: Fix race conditions and fd reuse bugs
* [Fix] Fuzzy TCP: Use pure ev_timer for session timeouts
* [Fix] Fuzzy TCP: Fix server replies and client event handling
* [Fix] Shutdown: Keep srv events active during shutdown to track auxiliary processes
* [Fix] ARC: Restore strict header ordering to comply with RFC 8617
* [Fix] ARC: Add ed25519 key support
* [Fix] Composites: Implement two-phase evaluation for postfilter dependencies
* [Fix] Composites: Use null-terminated string for symbol lookup
* [Fix] URL: Refactor extraction to prevent DoS with hash-based deduplication
* [Fix] URL: Add 50k URL limit with warning for DoS protection
* [Fix] URL: Skip HTML_DISPLAYED URLs in CTA detection
* [Fix] URL: Fix CTA priority preservation in extract_specific_urls
* [Fix] Bayes: Improve Redis server discovery
* [Fix] Bayes: Only bypass learn when header value matches
* [Fix] ESMTP: Robust per-recipient parsing in milter with safe cursor advance
* [Fix] ESMTP: Refcount ESMTP args in proxy_session_refresh to avoid use-after-free
* [Fix] ESMTP: Correct Lua stack cleanup in lua_task_get_rcpt_esmtp_args
* [Fix] HTML: Correct attribute value offset calculation for URL rewriting
* [Fix] HTML: Add HTML entity encoding for URL rewriting
* [Fix] HTML: Fix segfault due to incorrect HTML features access
* [Fix] HTML: Fix frequency-based ordering in domain hashing
* [Fix] HTML: Fix shingles hash generation bugs
* [Fix] HTML: Fix memory leaks in shingles generation
* [Fix] HTML: Fix memory management in html_cta.process_html_links
* [Fix] HTML: Fix CSS class normalization in fuzzy tokens
* [Fix] HTML: Fix cache key collision between text and HTML fuzzy hashes
* [Fix] OpenBSD: Fix kinfo_proc structure member names
* [Fix] OpenBSD: Disable Hyperscan (not available)
* [Fix] FreeBSD: Fix zstd package name
* [Fix] FreeBSD: Add IGNORE_OSVERSION for package version mismatches
* [Fix] NetBSD: Setup pkgin and PKG_PATH before installing packages
* [Fix] NetBSD: Fix missing dependencies and package names
* [Fix] BSD: Remove -j flag from ninja in all BSD workflows
* [Fix] Multimap: Handle symbols with leading numerals
* [Fix] Aliases: Prevent creation of malformed email addresses
* [Fix] Aliases: Fix alias loop detection for converging paths
* [Fix] Aliases: Fix is_local_domain to support backend objects
* [Fix] Aliases: Correct to_local when no recipients present
* [Fix] Aliases: Fix set_addr validation to prevent malformed addresses
* [Fix] MIME: Remove Authentication-Results and anonymize envelope-from in Received headers
* [Fix] Mempool: Prevent double-free in destructor cleanup
* [Fix] Rspamadm: Unbreak dnstool command
* [Fix] Integration tests: Fix ASAN configuration and startup diagnostics
* [Minor] Replace GHashTable with khash in fuzzy_check.c and lua_textpart_get_cta_urls
* [Minor] Update cache key prefix to match module name in llm_search_context
* [Minor] Fix llm_search_context to follow Rspamd idioms
* [Minor] Refactor llm_search_context to use lua_cache module
* [Minor] Address review comments in various modules
* [Minor] Fix droid usage
* [Minor] Use GPT-5 Codex for code reviews
* [Minor] Update libucl with automatic stack management
* [Rework] Prioritize CTA URLs in redirector and Lua helpers
* [Rework] RBL configuration: Add new from selectors, content_urls checks, and lower_utf8 for hashed domains
* [Rework] Make Bayes learn guards configurable
* [Rework] Refactor element visibility control to use Bootstrap classes
* [Rework] Use postconf utility for Postfix configuration in configwizard
* [Rework] Remove Lua-level HTTP header parsing in ESMTP args getters
* [Rework] Add CFG_REF_* macros with debug logging for config refcounting
* [Rework] Move OpenSSL providers from global to libs_ctx
* [Rework] Convert heap to fully intrusive kvec-based implementation
* [Rework] Add specialized pool types for long-lived and short-lived allocations
* [Rework] Improve memory pool destructors with smart preallocation based on pool type
* [Project] Restrict code review workflow to authorized maintainers
* [Project] Add Claude Code and Cursor AI assistant configuration
* [WebUI] Replace Glyphicons with FontAwesome SVG icons
* [WebUI] Update CodeJar to version 4.3.0
* [WebUI] Update Node.js and ESLint
* [WebUI] Update D3-based visualization libs
* [WebUI] Replace deprecated alert-error class with alert-danger
* [WebUI] Add search syntax hint to history table filter input
* [WebUI] Fix theme toggle default to auto
* [WebUI] Keep classifiers list when request is skipped
* [WebUI] Repopulate classifier dropdown
* [WebUI] Add comment for removeEventListener
* [WebUI] Fix icon rendering race condition in tab initialization
* [Test] Add comprehensive Lua unit tests for HTML URL rewriting
* [Test] Add unit tests for HTML URL rewriting patch engine
* [Test] Add functional tests for HTML fuzzy hashing
* [Test] Add ARC chain verification tests with multiple signatures
* [Test] Add e2e for classifier dropdown population
* [Test] Multimap symbol with leading numerals
* [Test] Sync public suffix list automatically
* [Test] Update JS linters
* [Test] Fix integration test environment variable passing
* [Test] Add detailed error output for integration test failures

2 weeks agoMerge pull request #5740 from rspamd/vstakhov-custom-actions-validation
Vsevolod Stakhov [Mon, 10 Nov 2025 15:04:39 +0000 (15:04 +0000)] 
Merge pull request #5740 from rspamd/vstakhov-custom-actions-validation

[Fix] Allow custom actions with flags in config validation

2 weeks agoMerge pull request #5733 from dragoangel/patch-14
Vsevolod Stakhov [Mon, 10 Nov 2025 14:46:31 +0000 (14:46 +0000)] 
Merge pull request #5733 from dragoangel/patch-14

[Feature] Update RBL configuration with new from selectors, and small refactor

2 weeks agoMerge pull request #5738 from moisseev/test
Vsevolod Stakhov [Mon, 10 Nov 2025 14:46:17 +0000 (14:46 +0000)] 
Merge pull request #5738 from moisseev/test

[Test] Update Node.js and ESLint

2 weeks agoMerge pull request #5739 from rspamd/vstakhov-rdns-fix-truncation
Vsevolod Stakhov [Mon, 10 Nov 2025 14:39:03 +0000 (14:39 +0000)] 
Merge pull request #5739 from rspamd/vstakhov-rdns-fix-truncation

[Fix] Preserve req->pos during reply validation to prevent packet truncation

2 weeks ago[Fix] Allow custom actions with flags in config validation 5740/head
Vsevolod Stakhov [Mon, 10 Nov 2025 13:58:25 +0000 (13:58 +0000)] 
[Fix] Allow custom actions with flags in config validation

The config validation was warning about unknown actions even when they
were valid custom actions defined with flags like 'no_threshold'.

Custom actions (e.g., malware, virus, hard-reject) are properly supported
by the C code but the Lua validation didn't recognize them, causing
spurious warnings.

Fix by checking if an unknown action is defined as an object with flags
before emitting the warning.

2 weeks ago[Minor] Set proper version
Vsevolod Stakhov [Mon, 10 Nov 2025 11:19:52 +0000 (11:19 +0000)] 
[Minor] Set proper version

2 weeks ago[Fix] Regenerate DNS transaction ID before copying packet to TCP buffer 5739/head
Vsevolod Stakhov [Mon, 10 Nov 2025 09:26:25 +0000 (09:26 +0000)] 
[Fix] Regenerate DNS transaction ID before copying packet to TCP buffer

When switching from UDP to TCP (e.g., on truncated response), the code
was copying the packet to the TCP output buffer before regenerating the
transaction ID to avoid collisions. This resulted in both UDP and TCP
packets having the same transaction ID.

Fix by moving the ID regeneration and IO channel switch logic before the
memcpy to the TCP output buffer, ensuring the TCP packet contains the
updated transaction ID.

2 weeks ago[Fix] Preserve req->pos during reply validation to prevent packet truncation on retra...
Vsevolod Stakhov [Mon, 10 Nov 2025 09:21:36 +0000 (09:21 +0000)] 
[Fix] Preserve req->pos during reply validation to prevent packet truncation on retransmit

The rdns_request_reply_cmp function modifies req->pos as a side effect
during reply validation. This caused packet truncation on retransmits
because req->pos (which tracks the full packet length) was overwritten
with the end position of the question section.

On timeout/retry, rdns_send_request would use the corrupted req->pos
value, resulting in truncated packets missing the OPT additional section.
This made resolvers like Knot and PowerDNS unable to parse retransmitted
packets.

Fix by saving and restoring req->pos around the reply comparison logic.

3 weeks ago[Minor] Replace GHashTable with khash in lua_textpart_get_cta_urls
Vsevolod Stakhov [Sun, 9 Nov 2025 15:27:45 +0000 (15:27 +0000)] 
[Minor] Replace GHashTable with khash in lua_textpart_get_cta_urls

Replace GHashTable with embedded khash for tracking seen URLs in
lua_textpart_get_cta_urls. khash provides better performance for
simple pointer sets and is already embedded in the project, reducing
external dependencies on GLib for this functionality.