fix(appsec): urldecode before lowercase on raw zones - #1872
Conversation
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018kCVups4eddfjUonQomPcs
|
Hello @mazzma12, ✅ The new VPATCH Rule is compliant, thank you for your contribution! |
|
Hello @mazzma12, Scenarios/AppSec Rule are compliant with the taxonomy, thank you for your contribution! |
There was a problem hiding this comment.
🟡 Changes recommended
The behavior change should be accompanied by appsec regression tests that specifically cover the percent-encoded-alpha bypass case that this PR fixes.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR hardens several CrowdSec appsec virtual patching rules against a percent-encoding evasion where lowercase ran before urldecode, allowing encoded bytes to decode into uppercase characters after case-folding and bypass lowercase-based matches.
Changes:
- Reorders
transformsteps from[lowercase, urldecode]to[urldecode, lowercase]for rules operating on raw/un-decoded Coraza zones (e.g.,URI_FULL,COOKIES,HEADERS,RAW_BODY). - Applies the fix across five CVE virtual patch rules where a single percent-encoding could previously evade detection.
File summaries
| File | Description |
|---|---|
| appsec-rules/crowdsecurity/vpatch-CVE-2026-63030.yaml | Reorders URI/body transform pipeline to decode before lowercasing for REST route confusion / SQLi detection. |
| appsec-rules/crowdsecurity/vpatch-CVE-2026-46725.yaml | Reorders cookie transform pipeline to decode before lowercasing for TYPO3 ceselector object injection detection. |
| appsec-rules/crowdsecurity/vpatch-CVE-2026-41940.yaml | Reorders cookie transform pipeline to decode before lowercasing for WHM auth-bypass cookie pattern detection. |
| appsec-rules/crowdsecurity/vpatch-CVE-2024-8181.yaml | Reorders URI transform pipeline to decode before lowercasing for Flowise auth-bypass endpoint detection. |
| appsec-rules/crowdsecurity/vpatch-CVE-2019-5418.yaml | Reorders header transform pipeline to decode before lowercasing for Rails Accept-header traversal detection. |
Review details
- Files reviewed: 5/5 changed files
- Comments generated: 4
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| transform: | ||
| - lowercase | ||
| - urldecode | ||
| - lowercase |
There was a problem hiding this comment.
Added in c99a962: second request GET /%41pi/v1/apikey?/api/v1/ping. Verified against the Coraza engine — misses with [lowercase, urldecode], matches with [urldecode, lowercase].
| transform: | ||
| - lowercase | ||
| - urldecode | ||
| - lowercase | ||
| - trim |
There was a problem hiding this comment.
Added in c99a962: fourth request with whostmgrsession=%3a%51SJN_sFdKZtCi2o_ and status_code_4 == 403. %51 decodes to Q, which fails ^:[a-z0-9_]+,?$ under the old order. The existing negative case (status_code_3 == 200) still returns 200 after the swap.
| transform: | ||
| - lowercase | ||
| - urldecode | ||
| - lowercase |
There was a problem hiding this comment.
Correct, the existing O%3A... payload matched under both orders. Added in c99a962: second request with T3_ceselector_1=%4F%3A28%3A..., which misses with the old order and matches with the new one.
| - and: | ||
| - zones: [URI_FULL] | ||
| transform: [lowercase, urldecode] | ||
| transform: [urldecode, lowercase] |
There was a problem hiding this comment.
Added in c99a962: second request POST /?rest_route=/%42atch/v1 with the same JSON body, so the RAW_BODY half of the conjunction still holds. %42 decodes to B, so contains: batch/v1 fails under the old order.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018kCVups4eddfjUonQomPcs
|
All four review comments addressed in c99a962. One rule has no regression request: I also changed the single-request tests from |
transform: [lowercase, urldecode]lowercases before decoding, so a percent-escape survives the fold and decodes to an uppercase letter afterwards, which the lowercase match then misses. Swapped to[urldecode, lowercase].These 5 rules use zones Coraza does not pre-decode (
COOKIES,HEADERS,URI_FULL,RAW_BODY), so a single percent-encoding is enough to evade them. Checked against the Coraza engine: for CVE-2026-46725,Cookie: t3_ceselector_x=%4F:8:"stdClass"does not match today and matches after the swap. PHP urldecodes$_COOKIE, so that payload still reachesunserialize().Same root cause as crowdsecurity/alert-context-rules#1107. A second PR covers the remaining 82 files, which use pre-decoded zones and need double encoding to bypass.
🤖 Generated with Claude Code
https://claude.ai/code/session_018kCVups4eddfjUonQomPcs