Skip to content

feat: add opt-in build flag to match v2's @rx anchor semantics (#3295)#3600

Open
fzipi wants to merge 3 commits into
owasp-modsecurity:v3/masterfrom
fzipi:fix/rx-regex-dollar-endonly-flag
Open

feat: add opt-in build flag to match v2's @rx anchor semantics (#3295)#3600
fzipi wants to merge 3 commits into
owasp-modsecurity:v3/masterfrom
fzipi:fix/rx-regex-dollar-endonly-flag

Conversation

@fzipi

@fzipi fzipi commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

Closes the behavioral gap described in #3295: @rx in libmodsecurity (v3) compiles patterns with PCRE(2)_DOTALL | PCRE(2)_MULTILINE, while ModSecurity v2's @rx (msre_op_rx_param_init) uses PCRE(2)_DOTALL | PCRE(2)_DOLLAR_ENDONLY. This means ^/$ anchors behave differently against multi-line values (e.g. multi-line ARGS) between the two engines, which is what surfaced as a CRS false-positive/negative report in coreruleset/coreruleset#3277.

Both commenters on #3295 agreed the target behavior should be v2's flags; the open question was only the rollout mechanism. This PR follows airween's proposal to use a build flag, mirroring the approach Coraza already shipped for the same issue (corazawaf/coraza#876, merged, gated behind coraza.rule.no_regex_multiline, off by default).

  • configure.ac: adds --enable-regex-dollar-endonly (off by default), defining MODSEC_REGEX_DOLLAR_ENDONLY when enabled.
  • src/utils/regex.h / regex.cc: Regex gains a multiLine constructor parameter, defaulting to true (current behavior). All existing callers (verifyCC, verifySSN, verifyCPF, internal chain/audit-log/collection regexes, etc.) are unaffected since they don't pass the new parameter.
  • src/operators/rx.cc / rx_global.cc: only @rx and @rxGlobal pass multiLine=false when the build flag is set, compiling with DOTALL | DOLLAR_ENDONLY instead of DOTALL | MULTILINE. This mirrors v2, where only @rx uses DOLLAR_ENDONLY while other operators (verifyCC, verifySSN, gsbLookup) keep MULTILINE unconditionally.
  • README.md: documents the new flag next to the existing PCRE2/PCRE section.

Test plan

  • Standalone harness exercising Utils::Regex directly against both the PCRE2 and legacy PCRE1 backends, confirming multiLine=false reproduces v2's dollar-endonly anchor semantics (no match across internal line breaks; trailing-newline $ behavior matches PCRE's DOLLAR_ENDONLY docs) while multiLine=true preserves current behavior.
  • Full ./configure && make succeeds with the flag both off (default) and on (--enable-regex-dollar-endonly=yes).
  • End-to-end: built a small program against the compiled library with SecRule ARGS:param1 "^hello.*world$" "deny" evaluated against a multi-line ARGS value. Default build blocks (reproducing the current v3 behavior described in Operator @rx has different flags in two engines #3295); with the flag enabled it does not block (matching v2).

🤖 Generated with Claude Code

libmodsecurity's shared Regex class compiles all patterns with
PCRE(2)_MULTILINE, while ModSecurity v2's @rx operator uses
PCRE(2)_DOLLAR_ENDONLY, so ^/$ anchor differently against multi-line
values between the two engines (owasp-modsecurity#3295).

Add --enable-regex-dollar-endonly, off by default, mirroring the
build-flag rollout Coraza used for the same issue
(corazawaf/coraza#876). When enabled, only @rx and @rxglobal compile
with DOLLAR_ENDONLY instead of MULTILINE; every other Regex caller
(verifyCC, verifySSN, verifyCPF, internal chain/audit-log regexes)
keeps its current behavior, matching how v2 itself only applies
DOLLAR_ENDONLY to @rx.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@fzipi fzipi changed the title Add opt-in build flag to match v2's @rx anchor semantics (#3295) feat: add opt-in build flag to match v2's @rx anchor semantics (#3295) Jul 19, 2026
@fzipi
fzipi requested a review from Copilot July 19, 2026 12:32
@fzipi fzipi added the 3.x Related to ModSecurity version 3.x label Jul 19, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an opt-in build-time switch to make libmodsecurity v3’s @rx/@rxGlobal anchor behavior match ModSecurity v2 by compiling those operators with DOLLAR_ENDONLY instead of MULTILINE, while keeping existing behavior as the default.

Changes:

  • Introduces --enable-regex-dollar-endonly to define MODSEC_REGEX_DOLLAR_ENDONLY at build time.
  • Extends Utils::Regex with a multiLine constructor parameter controlling whether MULTILINE or DOLLAR_ENDONLY is used.
  • Updates @rx and @rxGlobal to use the new mode when the build flag is enabled and documents the flag in README.md.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
configure.ac Adds a new --enable-regex-dollar-endonly configure switch that injects -DMODSEC_REGEX_DOLLAR_ENDONLY=1 into build flags.
src/utils/regex.h Extends the Regex constructor with a multiLine parameter (defaulting to current behavior).
src/utils/regex.cc Switches regex compilation options between MULTILINE and DOLLAR_ENDONLY based on multiLine.
src/operators/rx.cc Makes @rx select multiLine=false when MODSEC_REGEX_DOLLAR_ENDONLY is enabled.
src/operators/rx_global.cc Makes @rxGlobal select multiLine=false when MODSEC_REGEX_DOLLAR_ENDONLY is enabled.
README.md Documents the new build flag and the intended behavioral difference for anchors.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.md Outdated
Comment thread src/utils/regex.cc
- README: clarify that MULTILINE controls where ^/$ can anchor (per-line
  vs. whole-subject), while DOLLAR_ENDONLY only further refines $ against
  a trailing newline; DOTALL is unchanged either way so . still matches
  across internal line breaks.
- Add test/unit/regex_multiline_test.cc, a standalone regression test for
  the multiLine constructor parameter added to Utils::Regex, covering
  both the multiLine=true (default) and multiLine=false paths. Wired into
  test/Makefile.am as its own noinst_PROGRAMS binary and into
  test/test-suite.in / test-suite.sh (the existing dispatcher only knew
  how to run JSON test-case files against unit_tests/regression_tests).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread test/unit/regex_multiline_test.cc Outdated
Comment thread test/test-suite.sh
…ndalone test binary

Per @airween's review feedback: the regression test framework already
supports skipping a JSON test case at runtime via a "resource" key
(test/regression/regression.cc), matching it against a list of
compile-time-enabled features (WITH_CURL, WITH_LUA, WITH_LIBXML2, etc.).
Register "regex-dollar-endonly" the same way under
MODSEC_REGEX_DOLLAR_ENDONLY, and add
test/test-cases/regression/operator-rx-dollar-endonly.json gated on it,
covering both a single-line match (still blocks) and a multi-line ARGS
value (anchors no longer span line breaks). Builds without the flag
skip these two cases; builds with it pass.

This replaces the standalone regex_multiline_test.cc binary and its
Makefile.am/test-suite.in/test-suite.sh wiring from the previous commit,
which needlessly diverged from how every other test in this project is
structured.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Jul 19, 2026

Copy link
Copy Markdown

Quality Gate Passed Quality Gate passed

Issues
0 New issues
5 Accepted issues

Measures
0 Security Hotspots
No data about Coverage
0.0% Duplication on New Code

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3.x Related to ModSecurity version 3.x

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants