Description
Summary
The action parser refuses to load a rule when the value of ctl:ruleRemoveTargetByTag (or ctl:ruleRemoveTargetById) contains a @ character. The same rule loads cleanly under ModSecurity v2.
The cause appears to be in the scanner: @ is tokenized as the operator prefix (as in @rx, @detectXSS) and that interpretation leaks into action-value tokenization. Likely in src/parser/seclang-scanner.ll.
Affected
- libmodsecurity 3.0.15 (
owasp/modsecurity-crs:nginximage, current pinned digest) - ModSecurity-nginx connector
Reproducer
SecRule REQUEST_URI "@unconditionalMatch" \
"id:999990,\
phase:2,\
pass,\
nolog,\
ctl:ruleRemoveTargetByTag=attack-xss; XML://@*"Expected
Rule loads. XML://@* is a valid ModSecurity XPath target and is accepted as a SecRule variable in the same engine.
Actual
[emerg] "modsecurity_rules_file" directive Rules error.
Line: 6. Column: 47. Expecting an action, got: @*"
The error column always points at the @.
Bisect
Value passed to ctl:ruleRemoveTargetByTag |
Result |
|---|---|
attack-xss; XML:/* |
✓ loads |
attack-xss; XML://foo |
✓ loads |
attack-xss; XML://node |
✓ loads |
attack-xss; XML:/element |
✓ loads |
attack-xss; REQUEST_HEADERS:Foo |
✓ loads |
attack-xss; XML://@* |
✗ fails at @ |
attack-xss; XML://@foo |
✗ fails at @ |
attack-xss; XML://@ |
✗ fails at @ |
attack-xss; ARGS:@foo |
✗ fails at @ |
attack-xss; FOO@BAR |
✗ fails at @ |
So the problematic character is @, regardless of its position or what follows it. Quoting ('…') and backslash escaping (\@) are not honored.
ModSecurity v2 comparison
The same rule loads and runs correctly under Apache + mod_security2 2.9.x.
Impact
ctl:ruleRemoveTargetByTag / ctl:ruleRemoveTargetById cannot be used to runtime-toggle any target that includes a @ — which includes the entire XPath attribute axis (XML://@*, XML://@name, etc.). The only workaround is ctl:ruleRemoveById, which disables the whole rule rather than a single target.
Asks
- Allow
@(and ideally the full target/XPath grammar) insidectl:ruleRemoveTarget*values. - If a scanner change is non-trivial, document the limitation in the v3 reference manual.
Activity
airween commentedon May 14, 2026
@fzipi,
thanks for reporting this.
It's a very annoying bug, but I think it's easy to fix (with a minimum modification).
The problem is that the REMOVE_RULE_BY does not cover the character
@.Adding the
@solves it partially, but probably it would be much better to split up the tokens forruleRemoveBy...andruleRemoveTargetBy...cases.And of course, add as many tests as possible.
Jitterx69 commentedon May 14, 2026
@airween
If nobody’s working on this yet, I’d be down to patch it
airween commentedon May 14, 2026
Go for it!
Jitterx69 commentedon May 14, 2026
Hope it helps @airween
Add regression tests for ctl:ruleRemoveTarget with '@' (owasp-modsecu…
etiennemunnich commentedon May 30, 2026
Hi @fzipi — I'm working on #3526 and it overlaps this issue in the lexer, so flagging before either of us rebases.
#3526 adds a new scanner token class for the
ctl:ruleRemoveTargetById/ByTagvalue to supportCOLLECTION:/regex/patterns:Two things relevant here:
{ACTION_CTL_RULE_REMOVE_TARGET_BY_*}rules this issue points at, so a ctl:ruleRemoveTarget* rejects any target containing@(e.g. XPath attribute selectors) #3565 fix and feat: regex key support for ctl:ruleRemoveTargetById and ctl:ruleRemoveTargetByTag #3526 will collide on those lines. Worth sequencing deliberately.,(to keep chainedctl:actions splitting on comma) and also does not include@, so feat: regex key support for ctl:ruleRemoveTargetById and ctl:ruleRemoveTargetByTag #3526 as-is does not resolve this —XML:/*/@attrwould still be rejected.The fix looks like adding
@to the value char class(es):REMOVE_RULE_TARGET_VALUE, andREMOVE_RULE_BYif literal@should also work there. I'm already in this code, so I can fold that into #3526, or keep it separate — whichever ordering you prefer.Regression tests I'd add:
@:ctl:ruleRemoveTargetById=981176;XML:/*/@attrloads and removes the target (covers ctl:ruleRemoveTarget* rejects any target containing@(e.g. XPath attribute selectors) #3565 directly).@: aCOLLECTION:/.../pattern whose key contains@, confirming the regex path handles it.ctl:actions with a regex value still split correctly on,.I'll rebase #3526 on current master regardless.
Fix lexer rejection of '@' in ctl:ruleRemoveTarget actions (#3565)
Merge pull request #3589 from airween/Jitterx69/fix/issue-3565-ctl-re…