You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When there's a regular expression error due to SecPcreMatchLimit or SecPcreMatchLimitRecursion (i.e. MSC_PCRE_LIMITS_EXCEEDED), a rule using !@rx will say that the rule was triggered. However, failures with @rx will say that the rule was not triggered. I think both should assume the rule was not triggered. See coreruleset/coreruleset#3640 (comment) for additional context.
I checked this issue again and tried to figure out what would be the solution. I agree with your suggestion:
Expected behavior
I would expect !@rx to not trigger a rule if there's a MSC_PCRE_LIMITS_EXCEEDED error.
I took a look at @rx's behavior, and I think we don't need to care about "other direction" - I mean if a rule uses @rx PATTERN syntax and the MSC_PCRE_LIMITS_EXCEEDED is set then the rule won't trigger.
Here is the condition table:
Operator syntax
Operator evaluation result
MSC_PCRE_LIMITS_EXCEEDED is set
Rule result
!@rx PATTERN
false
no matter
not triggered
!@rx PATTERN
true
no
triggered
!@rx PATTERN
true
yes
not triggered
The last row is a new condition. We should implement this in both engines (mod_security2 and libmodsecurity3), but in first step only at the @rx operator (I mean this modification won't affect the other regex's behavior, eg. targets like ARGS:/^foo.*$/).
Hi @airween, I agree that the !@rx condition when MSC_PCRE_LIMITS_EXCEEDED happens is the only one that needs to be updated to not trigger the rule. Thanks!
Revisiting this one, with the mechanism from the code. Rx::evaluate returns false whenever the regex call fails (src/operators/rx.cc, after setting MSC_PCRE_LIMITS_EXCEEDED), and the generic negation in Operator::evaluateInternal (src/operators/operator.cc) then turns that into a match for !@rx. The fix @airween agreed to needs the error to be distinguishable from "no match": either a tri-state result from the operator, or a transaction flag set on regex error that the negation wrapper checks before flipping the result. The same applies to @rxGlobal and the other regex-backed operators. Confirmed bug.
Activity
airween commentedon Apr 19, 2024
Hi @ssigwart,
thanks for reporting, I will take a look at this issue soon.
airween commentedon Oct 14, 2024
Hi @ssigwart,
meanwhile I faced this problem somewhere else, now I can confirm this is a bug. Thanks for reporting.
ssigwart commentedon Oct 14, 2024
Great. Thanks, @airween.
airween commentedon Feb 12, 2025
Hi @ssigwart,
first of all, sorry for the long delay.
I checked this issue again and tried to figure out what would be the solution. I agree with your suggestion:
I took a look at
@rx's behavior, and I think we don't need to care about "other direction" - I mean if a rule uses@rx PATTERNsyntax and theMSC_PCRE_LIMITS_EXCEEDEDis set then the rule won't trigger.Here is the condition table:
!@rx PATTERN!@rx PATTERN!@rx PATTERNThe last row is a new condition. We should implement this in both engines (mod_security2 and libmodsecurity3), but in first step only at the
@rxoperator (I mean this modification won't affect the other regex's behavior, eg. targets likeARGS:/^foo.*$/).What do you think about this solution?
Please note this solution @marcstern, @dune73, @fzipi, @theseion.
Also note to @jptosso, @M4tteoP, @jcchavezs - for Coraza compatibility.
ssigwart commentedon Feb 12, 2025
Hi @airween, I agree that the
!@rxcondition whenMSC_PCRE_LIMITS_EXCEEDEDhappens is the only one that needs to be updated to not trigger the rule. Thanks!fzipi commentedon Feb 14, 2025
Sound good. This condition is specific to modsecurity, as Coraza does not not use pcre2 engine.
fzipi commentedon Oct 12, 2026
Revisiting this one, with the mechanism from the code.
Rx::evaluatereturnsfalsewhenever the regex call fails (src/operators/rx.cc, after settingMSC_PCRE_LIMITS_EXCEEDED), and the generic negation inOperator::evaluateInternal(src/operators/operator.cc) then turns that into a match for!@rx. The fix @airween agreed to needs the error to be distinguishable from "no match": either a tri-state result from the operator, or a transaction flag set on regex error that the negation wrapper checks before flipping the result. The same applies to@rxGlobaland the other regex-backed operators. Confirmed bug.