Repository navigation
Conversation
Within a double quoted operator parameter, an escaped double quote (")
now stands for a literal quote character, matching ModSecurity v2
behavior (Apache's ap_getword_conf performed this unescaping for v2).
Previously the parameter reached the operators with the escape
backslashes intact, so a rule such as
SecRule ARGS "@contains test()\"quote\"" never matched.
Fixes owasp-modsecurity#3750.
Co-authored-by: GeneralTony007 <144252170+GeneralTony007@users.noreply.github.com>
Walkthrough
Pre-merge checks:
|
|



Fixes #3750.
Problem
In v3, an escaped double quote inside a double-quoted operator parameter is not unescaped by the SecLang scanner, so a rule like the issue's:
keeps the literal two-character sequence
\"in the operator parameter instead of the intended", and the operator never matches a request argument containingtest()"quote".Fix
Add a small
unescapeOperatorParamhelper in the scanner, applied in the four actions of the two double-quoted operator-param lexer states (with and without macro expansion, with and without leading escape). The helper walks the parameter text: a backslash sets an escape flag and is kept; if the flagged character turns out to be a", the pending backslash is removed and a literal"is emitted; every other character is copied verbatim. Net effect:\"becomes"(the reported bug), and a backslash before any other character is preserved verbatim, so regex escapes such as\dare untouched.One escaping backslash is removed before a quote when the run has odd length; every other backslash remains unchanged. This matches the reported one-backslash case, not full Apache unescaping.
The generated
seclang-scanner.ccis regenerated with flex 2.6.4 (the CI image's version) through the repo's--enable-parser-generationpath; its diff is line-number churn plus the four helper calls.Tests
New regression file
test/test-cases/regression/operator-contains-escaped-quote.json(plus one line intest-suite.in) with four cases:test()"quote"(Rule returned 1);@rx ^\d+$still works, proving regex backslash escapes survive the helper;The file fails with the base scanner and passes after the change. Additional local boundary checks (macro expansion inside the parameter, backslash runs before a quote) pass; those are local verification, not part of the committed test file.
Test results (local)
Build env: pcre2 10.39, yajl 2.1.0, flex 2.6.4/bison, configure
--without-curl --without-lua --without-maxmind --without-geoip --without-ssdeep --without-lmdb --without-libxml --enable-assertions=yes --enable-parser-generation(jammy packages, same versions as the CI image).make check: TOTAL 5148, PASS 5053, SKIP 95, FAIL 0, ERROR 0. The 95 skips sit in test files for the disabled optional features (geo/maxmind, XML/libxml, Lua, inspectFile, fuzzyHash/ssdeep, remote-rules/curl, exec, and one pcre dollar-endonly variant); those code paths were not exercised in this environment, so they are unverified here rather than proven unaffected. The 4 new cases pass../unit_tests(broader than the automake list): 4336 total, 11 failed, 5 skipped. The 11 failures are all intransformations/phpArgsNames.json, match the comparison build with both scanner sources restored from the base commit; the new regression tests remained present, and that file is not in the automakemake checkTESTS list upstream; the 5 skips are geoLookup (feature disabled).make check-staticgate; the upstream gate excludes the generated parser/scanner sources (-iflags), which are the only changed .cc files.Scope note
The change touches only the scanner's double-quoted operator-param states. Single-quoted params, variable names, actions, and non-quoted free text are untouched.
Summary by CodeRabbit