From 1d4408fb087ded49dd9f08c1c3dc96d31231288e Mon Sep 17 00:00:00 2001 From: Felipe Zipitria Date: Tue, 31 Mar 2026 09:10:53 -0300 Subject: [PATCH 1/6] =?UTF-8?q?blog:=20add=20CRS=20migration=20series=20pa?= =?UTF-8?q?rt=206=20=E2=80=94=20false=20positive=20tuning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Covers two migration strategies (start fresh vs carry over), safe production cut-over phases (parallel detection, validation, cut-over), common false positive areas after the migration, and the new per-PL reporting model for systematic tuning. Co-Authored-By: Claude Sonnet 4.6 --- ...ating-from-crs-3-to-crs-4-part-6-tuning.md | 137 ++++++++++++++++++ .../2026/04/pexels-northern-29268627.jpg | Bin 0 -> 47336 bytes 2 files changed, 137 insertions(+) create mode 100644 content/blog/2026-05-04-migrating-from-crs-3-to-crs-4-part-6-tuning.md create mode 100644 static/images/2026/04/pexels-northern-29268627.jpg diff --git a/content/blog/2026-05-04-migrating-from-crs-3-to-crs-4-part-6-tuning.md b/content/blog/2026-05-04-migrating-from-crs-3-to-crs-4-part-6-tuning.md new file mode 100644 index 00000000..23b87cec --- /dev/null +++ b/content/blog/2026-05-04-migrating-from-crs-3-to-crs-4-part-6-tuning.md @@ -0,0 +1,137 @@ +--- +author: fzipi +categories: + - Blog +date: '2026-05-04T09:00:00-03:00' +tags: + - CRS-News + - Migration + - CRS-v4 +images: + - /images/2026/04/pexels-northern-29268627.jpg +title: 'Migrating from CRS 3.3 to CRS 4.25 LTS — Part 6: False Positive Tuning' +slug: 'migrating-crs-3-to-4-part-6-tuning' +--- + +This is Part 6 of the [CRS 3.3 → 4.25 LTS migration series]({{< ref "blog/2026-03-30-migrating-from-crs-3-to-crs-4-part-1-overview.md" >}}). Part 5 covered rule changes and how to audit your existing exclusions. This post covers the tuning phase itself — the practical work of establishing a clean CRS 4 baseline for your applications. + +{{< figure src="/images/2026/04/pexels-northern-29268627.jpg" >}}*© Dave H (pexels.com)* + +## Two Migration Strategies + +There are two approaches to handling false positive tuning during the migration. Neither is universally better — choose based on the size and complexity of your existing setup. + +### Strategy A: Start Fresh + +Discard your existing CRS 3 exclusions entirely and retune from scratch with CRS 4. + +**When this makes sense:** +- Your application has changed significantly since you last tuned CRS +- Your CRS 3 exclusion set is large, poorly documented, or has accumulated exclusions whose original reasons are no longer clear +- You run at PL1 with a relatively small exclusion set +- You are migrating to a different WAF engine at the same time + +**How to do it:** +1. Install CRS 4.25.0 with a clean `crs-setup.conf` at your target paranoia level +2. Install any required application exclusion plugins (Part 3) but do not add any custom exclusions yet +3. Set the WAF to detection mode (log but do not block) +4. Run detection mode for at least two weeks, covering all application workflows +5. Collect false positives from your WAF logs and add exclusions for legitimate traffic +6. Re-enable blocking when the false positive rate is acceptable + +The advantage: you start clean, without carrying forward exclusions that may have masked other issues. The disadvantage: this requires the application traffic to actually exercise all code paths during the detection phase. If you have infrequently-used admin workflows, they must be tested manually. + +### Strategy B: Carry Over Existing Exclusions + +Map your CRS 3 exclusions to CRS 4 equivalents and migrate them. + +**When this makes sense:** +- You run at PL2 or higher with a large, well-maintained exclusion set +- Your application is stable and complex, making a full retune expensive +- You have strong coverage of application traffic in your detection logs from CRS 3 + +**How to do it:** +1. Follow the exclusion audit described in [Part 5]({{< ref "blog/2026-04-27-migrating-from-crs-3-to-crs-4-part-5-rule-changes.md" >}}) to map each old rule ID to its CRS 4 equivalent +2. Remove exclusions for rules that no longer exist (and verify the underlying issue is gone) +3. Update rule IDs for renamed and renumbered rules +4. Install CRS 4 with the updated exclusion set in detection mode +5. Run detection mode for one to two weeks to catch anything the mapping missed +6. Add new exclusions for any new false positives +7. Re-enable blocking + +The advantage: less manual re-testing of application workflows. The disadvantage: you may carry forward exclusions that are now unnecessary, slightly weakening your detection. + +## Running a Safe Production Migration + +Regardless of which strategy you choose, the migration sequence for production should be: + +### Phase 1: Parallel Detection (1-2 weeks) + +Run CRS 4 in detection mode in parallel with your existing CRS 3 blocking setup. There are a few ways to achieve this: + +**Dual WAF deployment.** Route a copy of your traffic (via mirroring or a dedicated logging endpoint) through CRS 4 in detection mode, while CRS 3 continues blocking for real traffic. Compare the CRS 4 detection results against known good requests in your access logs. + +**Single WAF, detection mode.** If a parallel setup is not practical, swap CRS 3 for CRS 4 in pure detection mode. You lose blocking during this phase, so only do this if your threat model allows a temporary blocking gap (e.g. you have another upstream protection layer). + +**WAF-engine anomaly logging.** Some WAF engine setups allow you to log anomaly score results without blocking, even when blocking is technically enabled, by setting the anomaly threshold very high (e.g. `9999`). Set your CRS 4 thresholds to `9999` during the detection phase so that nothing is blocked even if the score exceeds the normal threshold. + +### Phase 2: Validation + +After the detection phase, review your CRS 4 detection logs: + +- Count distinct rule IDs that fired +- For each firing rule, determine whether the trigger was a legitimate request or actual attack traffic +- For legitimate requests that triggered rules, add targeted exclusions +- Check that known attack traffic you tested is still detected + +The CRS 4 per-PL score breakdown in logs (covered in Part 4) makes this easier than it was in CRS 3 — you can see at a glance which paranoia level is responsible for each detection. + +### Phase 3: Cut Over + +Switch CRS 4 from detection mode to blocking mode by restoring your normal anomaly thresholds. Keep enhanced logging enabled for the first week after cut-over to catch anything the detection phase missed. + +## Common False Positive Areas to Check + +Based on the changes covered in earlier posts in this series, these are the areas most likely to produce new false positives after the CRS 3 → 4 migration: + +**Response-phase web shell rules.** Applications that return debugging output or verbose error messages containing shell-like text. Check your application's error pages, debug endpoints, and admin panels. + +**Restricted headers — basic list.** Requests that include `Content-Encoding`, `X-HTTP-Method-Override`, or `Expect`. These are blocked at all paranoia levels. Common sources: upload clients that set `Content-Encoding`, JavaScript frameworks using `X-HTTP-Method-Override` for form method override, and .NET clients using `Expect: 100-continue`. + +**Restricted headers — extended list.** Requests that include `Accept-Charset`. This is only blocked at higher paranoia levels (PL2+) since it still appears in some legitimate clients. If you run at PL1, this will not trigger. + +**PL redistribution.** If you run at PL2, some rules that were PL3 in CRS 3 are now PL2 in CRS 4 and will fire where they did not before. The new firings are most common in SQL injection and XSS detection rules. + +**Plugin exclusions.** If you use application exclusion plugins (Part 3), the plugin rule IDs are different from the CRS 3 exclusion rule IDs. The plugins may have broader or narrower coverage than the original CRS 3 exclusion files. + +## Using the New Reporting Model for Tuning + +CRS 4's per-PL score breakdown makes tuning more systematic. For each false positive in your logs: + +1. Note the rule ID and the PL it belongs to +2. Note the request URI, method, and the specific parameter that triggered the rule +3. Decide: is this a real false positive (legitimate application behaviour), or is the application doing something it should not? + +For real false positives, write the exclusion as narrowly as possible. The CRS-recommended pattern is: + +```apache +# In REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf +# Exclude rule 941100 (XSS via libinjection) for the /editor/save path +SecRule REQUEST_URI "@beginsWith /editor/save" \ + "id:1001,phase:2,pass,nolog,\ + ctl:ruleRemoveTargetById=941100;ARGS:content" +``` + +Prefer path-scoped, parameter-scoped exclusions over global rule removals. A global `SecRuleRemoveById 941100` removes XSS detection from your entire application; the above removes it only for the `content` parameter on the specific path where the rich text editor needs it. + +## After the Migration: Maintaining Your Exclusion Set + +One benefit of migrating to CRS 4.25.0 LTS is that the rule set is stable. The LTS backport policy does not allow new rules, PL changes, or refactoring to land on the LTS branch. This means your exclusions will not be invalidated by LTS point releases — only security fixes are backported, and those are cherry-picked with care. + +When a new LTS point release ships (quarterly), review the release notes before upgrading. The release notes will list every change on the LTS branch. If a security fix modifies a rule you have excluded, review your exclusion. + +## What's Next + +[Part 7]({{< ref "blog/2026-05-11-migrating-from-crs-3-to-crs-4-part-7-engines.md" >}}) covers engine-specific considerations — the support matrix for ModSecurity v2, ModSecurity v3, and Coraza, differences in plugin compatibility across engines, and the new Docker image tagging scheme. + +*Felipe Zipitria, CRS Co-Lead* diff --git a/static/images/2026/04/pexels-northern-29268627.jpg b/static/images/2026/04/pexels-northern-29268627.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0fa5d4f70b9d3f70af26c7508431b74135b46447 GIT binary patch literal 47336 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 literal 0 HcmV?d00001 From 50ccaeca268b3500c192baea584a336eda9d6539 Mon Sep 17 00:00:00 2001 From: Felipe Zipitria Date: Tue, 31 Mar 2026 12:02:33 -0300 Subject: [PATCH 2/6] chore: demote broken ref links to warnings Sets refLinksErrorLevel=WARNING so cross-post ref links don't break the build when sibling posts don't yet exist on the same branch. Co-Authored-By: Claude Sonnet 4.6 --- config/_default/hugo.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/config/_default/hugo.yaml b/config/_default/hugo.yaml index 3d004a76..1809f01e 100644 --- a/config/_default/hugo.yaml +++ b/config/_default/hugo.yaml @@ -9,6 +9,7 @@ timeZone: "Europe/London" enableEmoji: true enableGitInfo: true +refLinksErrorLevel: WARNING ######################## i18n #################### # Auto-detect Chinese/Japanese/Korean Languages in the content. see: https://gohugo.io/getting-started/configuration/#hascjklanguage hasCJKLanguage: false From 863e8a7f5892445cd6c047401bbee82c543a7963 Mon Sep 17 00:00:00 2001 From: Felipe Zipitria Date: Wed, 1 Apr 2026 11:10:52 -0300 Subject: [PATCH 3/6] fix: use proper figure shortcode caption and attr parameters Co-Authored-By: Claude Opus 4.6 (1M context) --- .../2026-05-04-migrating-from-crs-3-to-crs-4-part-6-tuning.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/blog/2026-05-04-migrating-from-crs-3-to-crs-4-part-6-tuning.md b/content/blog/2026-05-04-migrating-from-crs-3-to-crs-4-part-6-tuning.md index 23b87cec..86bb8281 100644 --- a/content/blog/2026-05-04-migrating-from-crs-3-to-crs-4-part-6-tuning.md +++ b/content/blog/2026-05-04-migrating-from-crs-3-to-crs-4-part-6-tuning.md @@ -15,7 +15,7 @@ slug: 'migrating-crs-3-to-4-part-6-tuning' This is Part 6 of the [CRS 3.3 → 4.25 LTS migration series]({{< ref "blog/2026-03-30-migrating-from-crs-3-to-crs-4-part-1-overview.md" >}}). Part 5 covered rule changes and how to audit your existing exclusions. This post covers the tuning phase itself — the practical work of establishing a clean CRS 4 baseline for your applications. -{{< figure src="/images/2026/04/pexels-northern-29268627.jpg" >}}*© Dave H (pexels.com)* +{{< figure src="/images/2026/04/pexels-northern-29268627.jpg" caption="Fine-tuning for production" attr="Dave H on Pexels" attrlink="https://www.pexels.com" >}} ## Two Migration Strategies From 238ff8402bc4b888c555255574a594e2c3183c08 Mon Sep 17 00:00:00 2001 From: Felipe Zipitria Date: Wed, 1 Apr 2026 11:14:54 -0300 Subject: [PATCH 4/6] fix: replace author byline with related-pages shortcode The author is already shown from the front matter. Adds the related-pages shortcode to cross-link migration series posts. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../2026-05-04-migrating-from-crs-3-to-crs-4-part-6-tuning.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/blog/2026-05-04-migrating-from-crs-3-to-crs-4-part-6-tuning.md b/content/blog/2026-05-04-migrating-from-crs-3-to-crs-4-part-6-tuning.md index 86bb8281..c6f2301d 100644 --- a/content/blog/2026-05-04-migrating-from-crs-3-to-crs-4-part-6-tuning.md +++ b/content/blog/2026-05-04-migrating-from-crs-3-to-crs-4-part-6-tuning.md @@ -134,4 +134,4 @@ When a new LTS point release ships (quarterly), review the release notes before [Part 7]({{< ref "blog/2026-05-11-migrating-from-crs-3-to-crs-4-part-7-engines.md" >}}) covers engine-specific considerations — the support matrix for ModSecurity v2, ModSecurity v3, and Coraza, differences in plugin compatibility across engines, and the new Docker image tagging scheme. -*Felipe Zipitria, CRS Co-Lead* +{{< related-pages "Migration" "CRS-v4" >}} From 2d9e0f0f349fedbfb23c9038136ba54943d0b968 Mon Sep 17 00:00:00 2001 From: Felipe Zipitria Date: Thu, 2 Apr 2026 11:34:22 -0300 Subject: [PATCH 5/6] fix: add What's Next section to part 1 linking to part 2 Co-Authored-By: Claude Opus 4.6 (1M context) --- ...ing-from-crs-3-to-crs-4-part-1-overview.md | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 content/blog/2026-03-30-migrating-from-crs-3-to-crs-4-part-1-overview.md diff --git a/content/blog/2026-03-30-migrating-from-crs-3-to-crs-4-part-1-overview.md b/content/blog/2026-03-30-migrating-from-crs-3-to-crs-4-part-1-overview.md new file mode 100644 index 00000000..a200fc36 --- /dev/null +++ b/content/blog/2026-03-30-migrating-from-crs-3-to-crs-4-part-1-overview.md @@ -0,0 +1,75 @@ +--- +author: fzipi +categories: + - Blog +date: '2026-03-30T09:00:00-03:00' +tags: + - CRS-News + - Migration + - CRS-v4 +images: + - /images/2026/04/pexels-toulouse-18332033.jpg +title: 'Migrating from CRS 3.3 to CRS 4.25 LTS — Part 1: Overview' +slug: 'migrating-crs-3-to-4-part-1-overview' +--- + +The release of [CRS v4.25.0 LTS]({{< ref "blog/2026-03-28-announcing-crs-v4-25-lts.md" >}}) marks the moment the CRS 4 generation has its long-term support anchor. If you have been running CRS 3.3.x — waiting for stability before committing to an upgrade — that moment is now. + +This is the first post in a series walking through everything you need to know to migrate from CRS 3.3.9 (the last CRS 3 LTS release) to CRS 4.25.0 LTS. The series is not a quick upgrade guide. It is a deliberate, post-by-post treatment of each dimension of the migration so that you can plan and execute without surprises. + +{{< figure src="/images/2026/04/pexels-toulouse-18332033.jpg" caption="Charting the path from CRS 3 to CRS 4" attr="Maël BALLAND on Pexels" attrlink="https://www.pexels.com" >}} + +## Why Migrate? + +CRS 3.3.x is in security-only maintenance. It receives backports for confirmed security vulnerabilities but nothing else: no false positive fixes, no new detections, no engine compatibility improvements. Every month you stay on CRS 3.3.x, the gap between your deployment and the state of the art widens. + +CRS 4.25.0 LTS closes that gap and gives you a new stability baseline. Its [backport policy](https://github.com/coreruleset/coreruleset/blob/lts/v4.25.x/BACKPORT_POLICY.md) is explicit about what goes in (security fixes, regressions, critical false positive fixes) and what does not (new features, refactoring, toolchain changes). You get meaningful improvements without being forced to track monthly releases. + +## What Changed at a Glance + +CRS 4 is not a drop-in replacement for CRS 3. There are roughly 500 changes between the two release lines. The ones that matter most for migration fall into a handful of categories: + +**Plugin architecture.** This is the biggest structural change. Application-specific rule exclusion packages — previously shipped as optional files inside the CRS release tarball — are no longer part of the core rule set. They are now separate plugins, installed independently. If you use any application exclusion package (WordPress, Nextcloud, phpBB, phpMyAdmin, or others), you will need to install the corresponding plugin before your existing exclusion coverage is restored. + +**Configuration file changes.** The `crs-setup.conf` file has new variables, renamed variables, and removed variables. You cannot simply drop your old `crs-setup.conf` into a CRS 4 installation and expect things to work. Anomaly scoring variables were renamed for consistency, and several new options were added. + +**Rule-level changes.** Hundreds of rules were modified, reorganized, or removed. Many rules moved between paranoia levels as part of a broad effort to spread detection better across PL1–PL4. New rule categories were added (notably, response-phase web shell detection). Some HTTP behaviours that were tolerated in CRS 3 (HTTP/0.9) were dropped, and new ones were added (HTTP/3, RE2/Hyperscan compatibility). + +**Anomaly scoring and reporting.** The variables used to accumulate and report anomaly scores were refactored. The old `980xxx` reporting rules were replaced with new, granular reporting logic. A new `blocking_early` option allows anomaly evaluation at the end of phase 1 (in addition to phase 2) and at the end of phase 3 (in addition to phase 4). + +**Engine compatibility.** All formerly PCRE-only regular expressions are now compatible with the RE2 and Hyperscan engines. ModSecurity v2, ModSecurity v3 (libmodsecurity), and Coraza are all supported, though with differences in capability. + +## What This Migration Is Not + +It is worth being direct about what this migration is not. + +**It is not a drop-in upgrade.** Running `cp -r crs4/ crs3/` and reloading your WAF will cause problems. Your old `crs-setup.conf` has variables that no longer exist in CRS 4 and is missing variables that CRS 4 requires. Your old exclusion rules may reference rule IDs that have changed. Your application exclusion packages will simply be absent until you install their plugin replacements. + +**It does not preserve your false positive tuning automatically.** Rules have moved between paranoia levels. Rule IDs have changed or been removed. Exclusions you wrote against specific rule IDs in CRS 3 need to be reviewed against the CRS 4 rule set before you go live. + +**It does not require starting from scratch.** A systematic approach — covered in detail in Part 6 of this series — lets you carry forward your existing tuning with a clear mapping between old and new rule IDs. + +## What to Expect From Each Post in the Series + +The series covers the migration in six more posts after this one: + +- **Part 2: Configuration** — A side-by-side walk through the `crs-setup.conf` changes, including every renamed and new variable. Includes a migration checklist. +- **Part 3: Plugin Architecture** — The conceptual model, how to install plugins, the official plugin registry, and a mapping from every CRS 3 application exclusion package to its CRS 4 plugin equivalent. +- **Part 4: Anomaly Scoring and Reporting** — The renamed scoring variables, the new reporting model, early blocking, and how paranoia level redistribution affects your anomaly score baseline. +- **Part 5: Rule Changes** — New rule categories, removed and reorganized rules, RE2/Hyperscan compatibility, and how to audit your existing `SecRuleRemoveById` and exclusion rules against the new rule set. +- **Part 6: False Positive Tuning** — Two migration strategies (start fresh vs. carry over), a step-by-step method for mapping old exclusions to new rule IDs, and how to run a production migration in shadow mode. +- **Part 7: Engine-Specific Notes** — The CRS 4 engine support matrix, differences between ModSecurity v2, ModSecurity v3, and Coraza, and the container image tagging scheme. + +## Before You Start + +Before reading the rest of this series, do two things. + +First, download CRS v4.25.0 and open the `crs-setup.conf.example` alongside your existing `crs-setup.conf`. Having both files open makes the configuration changes in Part 2 immediately concrete. + +Second, open the [CRS 4.0 CHANGES.md](https://github.com/coreruleset/coreruleset/blob/v4.0/dev/CHANGES.md) on GitHub. It is a long file, but it is the authoritative record of what changed. You do not need to read it end to end now — the series will reference specific entries — but knowing it exists and how to search it will be useful throughout. + +## What's Next + +[Part 2]({{< ref "blog/2026-04-06-migrating-from-crs-3-to-crs-4-part-2-configuration.md" >}}) covers the configuration file changes in detail — a side-by-side walk through every renamed, removed, and new variable in `crs-setup.conf`, plus a migration checklist and an interactive tool to convert your CRS 3 config. + +{{< related-pages "Migration" "CRS-v4" >}} From 2130fd3d4721337c9c48c6d0813f59398c7ca3e9 Mon Sep 17 00:00:00 2001 From: Felipe Zipitria Date: Thu, 7 May 2026 11:40:18 -0300 Subject: [PATCH 6/6] fix: address PR feedback on part 6 tuning post - Clarify that migration strategies are independent of rollout, and you do not have to turn off your WAF to validate CRS 4 - Restructure Phase 1 detection options: rename to "Detection-Mode Validation" and label dual-WAF as the only true parallel option; clarify single-WAF and anomaly-threshold-override approaches swap CRS 3 for CRS 4 (no rule ID conflicts) and call out the anomaly-threshold trick as a fallback when the engine has no detection-only switch - Suggest configuring the client (e.g. .NET Expect: 100-continue) before adding a WAF exclusion for restricted headers - Move SecRule exclusion example from phase 2 to phase 1 --- ...igrating-from-crs-3-to-crs-4-part-6-tuning.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/content/blog/2026-05-04-migrating-from-crs-3-to-crs-4-part-6-tuning.md b/content/blog/2026-05-04-migrating-from-crs-3-to-crs-4-part-6-tuning.md index c6f2301d..99796c51 100644 --- a/content/blog/2026-05-04-migrating-from-crs-3-to-crs-4-part-6-tuning.md +++ b/content/blog/2026-05-04-migrating-from-crs-3-to-crs-4-part-6-tuning.md @@ -21,6 +21,8 @@ This is Part 6 of the [CRS 3.3 → 4.25 LTS migration series]({{< ref "blog/2026 There are two approaches to handling false positive tuning during the migration. Neither is universally better — choose based on the size and complexity of your existing setup. +Both strategies describe how you build the CRS 4 exclusion set. They are independent of how you roll the new rule set out to production: you do **not** have to turn your existing WAF off to run either of them. The parallel rollout options that let you keep CRS 3 blocking while you validate CRS 4 are covered in [Running a Safe Production Migration](#running-a-safe-production-migration) below. + ### Strategy A: Start Fresh Discard your existing CRS 3 exclusions entirely and retune from scratch with CRS 4. @@ -65,15 +67,15 @@ The advantage: less manual re-testing of application workflows. The disadvantage Regardless of which strategy you choose, the migration sequence for production should be: -### Phase 1: Parallel Detection (1-2 weeks) +### Phase 1: Detection-Mode Validation (1-2 weeks) -Run CRS 4 in detection mode in parallel with your existing CRS 3 blocking setup. There are a few ways to achieve this: +Run CRS 4 in detection mode for one to two weeks (or until you have observed peak traffic and exercised every critical workflow at least once) so you can review what it would have blocked before any of it actually blocks. There are three ways to set this up; only the first is truly parallel — the others swap CRS 3 for CRS 4 in a single engine and rely on the engine not to block. -**Dual WAF deployment.** Route a copy of your traffic (via mirroring or a dedicated logging endpoint) through CRS 4 in detection mode, while CRS 3 continues blocking for real traffic. Compare the CRS 4 detection results against known good requests in your access logs. +**Option A: Dual WAF deployment (true parallel).** Route a copy of your traffic — via traffic mirroring, a sidecar engine, or a dedicated logging endpoint — through a second WAF instance running CRS 4 in detection mode, while your production WAF continues to run CRS 3 in blocking mode. CRS 3 keeps protecting real users; CRS 4 sees the same requests and records what it would have done. Compare the CRS 4 detection log against your access logs to find false positives. This is the safest option and the one to prefer when your environment supports it. -**Single WAF, detection mode.** If a parallel setup is not practical, swap CRS 3 for CRS 4 in pure detection mode. You lose blocking during this phase, so only do this if your threat model allows a temporary blocking gap (e.g. you have another upstream protection layer). +**Option B: Single WAF, detection mode.** If you cannot run a second engine, swap CRS 3 for CRS 4 on your existing WAF and put it in pure detection mode (CRS 3 is no longer active — running both rule sets in the same engine is not supported because of rule ID conflicts). You lose blocking for this phase, so only choose this if your threat model allows a temporary gap, for example because you have another upstream protection layer (CDN WAF, edge proxy, application-level controls). -**WAF-engine anomaly logging.** Some WAF engine setups allow you to log anomaly score results without blocking, even when blocking is technically enabled, by setting the anomaly threshold very high (e.g. `9999`). Set your CRS 4 thresholds to `9999` during the detection phase so that nothing is blocked even if the score exceeds the normal threshold. +**Option C: Single WAF, anomaly-threshold override.** Some engines do not have a clean detection-only switch, or you want CRS 4 fully wired into the production engine (alerting, audit logs, plugin loading) without it actually blocking. Swap CRS 3 for CRS 4 as in option B, but instead of toggling detection mode, raise the inbound and outbound anomaly score thresholds to a value the score will never reach in practice (for example `9999`). Blocking is technically enabled but functionally disabled — the engine evaluates every rule, you get the score breakdown in your logs, and nothing is rejected. Restore the normal thresholds when you cut over. ### Phase 2: Validation @@ -96,7 +98,7 @@ Based on the changes covered in earlier posts in this series, these are the area **Response-phase web shell rules.** Applications that return debugging output or verbose error messages containing shell-like text. Check your application's error pages, debug endpoints, and admin panels. -**Restricted headers — basic list.** Requests that include `Content-Encoding`, `X-HTTP-Method-Override`, or `Expect`. These are blocked at all paranoia levels. Common sources: upload clients that set `Content-Encoding`, JavaScript frameworks using `X-HTTP-Method-Override` for form method override, and .NET clients using `Expect: 100-continue`. +**Restricted headers — basic list.** Requests that include `Content-Encoding`, `X-HTTP-Method-Override`, or `Expect`. These are blocked at all paranoia levels. Common sources: upload clients that set `Content-Encoding`, JavaScript frameworks using `X-HTTP-Method-Override` for form method override, and .NET clients using `Expect: 100-continue`. Before adding a WAF exclusion, check whether the client itself can be configured not to send the header — `Expect: 100-continue` from .NET, for example, is controlled by `ServicePointManager.Expect100Continue` (or `HttpClientHandler` in newer code), and adjusting the application is usually preferable to weakening the rule. **Restricted headers — extended list.** Requests that include `Accept-Charset`. This is only blocked at higher paranoia levels (PL2+) since it still appears in some legitimate clients. If you run at PL1, this will not trigger. @@ -118,7 +120,7 @@ For real false positives, write the exclusion as narrowly as possible. The CRS-r # In REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf # Exclude rule 941100 (XSS via libinjection) for the /editor/save path SecRule REQUEST_URI "@beginsWith /editor/save" \ - "id:1001,phase:2,pass,nolog,\ + "id:1001,phase:1,pass,nolog,\ ctl:ruleRemoveTargetById=941100;ARGS:content" ```