Tuning OWASP CRS: Cutting False Positives Without Losing Coverage
OWASP CRS is powerful but noisy out of the box. A practical, ordered method to reduce false positives while keeping real attacks blocked.

Nearly every WAF gets switched off the same way. Someone enables the OWASP Core Rule Set, turns the sensitivity up, legitimate traffic starts getting blocked, the support tickets pile in, and by Thursday the thing is running in log-only "for now" — which, as we all know, means forever.
The rule set isn't the problem. CRS is one of the best things in open web security. The problem is that people tune it by panicking: deleting whatever rule fired last, until coverage is swiss cheese. There's a calmer way, and it's mostly about doing things in the right order.
Why it over-blocks in the first place
CRS scores a request against a lot of rules and blocks when the total crosses a threshold. Crank the "paranoia level" and it inspects harder — catching more attacks, sure, but also more coincidences: a rich-text comment, a base64 blob, a URL sitting in a query parameter. Tuning is really just the work of separating signal from noise without blinding the detector in the process.
The order that actually works
Start in log mode and leave it there for a week. Never tune against live users in blocking mode — collect what CRS would have blocked across a representative stretch of traffic first. You can't fix what you haven't measured.
Lower the sensitivity before you touch anything else. Most false positives evaporate the moment you stop running maximum paranoia on an app that doesn't need it. This one step usually does more than the rest combined.
Then reach for the specific rule. If one rule is behind most of the noise, turn down its influence rather than deleting it outright.
Scope exclusions tight. Exclude a rule on a specific path or parameter — never globally. "This endpoint accepts HTML" is a reason to relax one rule on one route, not the whole site.
Save the block threshold for last. It's the blunt instrument. Only lean on it after the precise tools have done their work.
How WAFio keeps this from going sideways
WAFio runs CRS through Coraza in detection-only mode and lets a central decision engine make the actual call from the combined score. In practice that means a few things. Per-project sensitivity — Safe, Balanced, Aggressive — is your main false-positive lever, and rules above your level simply don't apply. Your block and log thresholds are explicit and versioned, not buried in a config file nobody remembers editing. Path policies let you weaken or skip specific rules or tags on specific routes, so one noisy endpoint never forces you to loosen the entire site. And because the semantic engines run alongside CRS, turning a CRS rule down rarely leaves a whole attack class uncovered.
Measure, don't guess
Every decision keeps the signals that fired, so tuning becomes evidence instead of superstition — you can see precisely which rule matched which part of which request. Tune to the traffic you actually serve, re-check after each change, and keep your application-side validation no matter what the WAF says.
Keep the coverage, lose the noise
Do it in this order and you end up with something rarer than it should be: a WAF your team trusts enough to leave in blocking mode — which, in the end, is the only mode that protects anyone. For more on how semantic evidence takes the pressure off brittle rules, read Why Semantic Scan, or play with thresholds and sensitivity in the demo.