Most WAFs Block 90 Percent False Positives. Here Is How We Tune Them.
Cybersecurity
Out-of-the-box WAF rule sets are calibrated for an average application that does not exist. The block rate looks impressive in the dashboard and is mostly noise. A practitioner's guide to actually useful WAF tuning.
By Arjun Raghavan, Security & Systems Lead, BIPI · March 31, 2026 · 7 min read
Open the WAF dashboard for a typical mid-market SaaS. Block count: 50,000 yesterday. Top blocked rule: SQL injection. Top source country: Russia. The CISO sees a healthy security posture. The reality is that 90 percent of those blocks are false positives, the SQL injection rule is firing on legitimate API queries with apostrophes in them, and the actual attacks are passing through unblocked because they do not match the noisy patterns.
WAFs are not bad. Default rule sets are bad. The work to make a WAF useful is the same kind of detection engineering as SIEM tuning, and most teams skip it because the dashboard already shows big numbers.
What the default rule sets are doing
Default OWASP CRS rules, AWS managed rule groups, Cloudflare's free ruleset, all of them are calibrated for a generic web application: form-based login, simple GET/POST endpoints, traditional cookie session. Modern applications do not look like that. They have JSON APIs, JWTs in headers, GraphQL queries with arbitrary nesting, file upload endpoints with binary content. Most of the default rules trigger on legitimate traffic from these patterns.
The first time a team turns the rules on, every API client breaks. The team panics and either disables the rule entirely (now you have no protection) or moves to detection-only mode (now you have alerts nobody reads). Either is the wrong answer.
Step 1: Path-based scoping
Different paths have different threat models. Your /api/v1/users/upload endpoint accepts file uploads with binary content. Your /api/v1/auth/login accepts a JSON body with email and password. Your /admin/sql-runner (if you have one) accepts arbitrary SQL because that is its job.
Apply different rule sets to different paths. SQL injection rules on the SQL runner are pure false positives. SQL injection rules on auth endpoints are useful. Rate limit rules on file upload should be different from rate limits on login.
One rule set for the whole site is the equivalent of 'check all log sources with the same SIEM rule.' Nobody would do that for SIEM. Everyone does it for WAF.
Step 2: Method and content-type filtering
POST endpoints with application/json bodies do not have form parameters. SQL injection rules that look in form parameters should not run on JSON requests. GraphQL endpoints have their own threat model: introspection queries, depth limit, alias overload, batching attacks. These do not match traditional WAF patterns at all.
Adjust the WAF to skip rules that do not apply to the request shape. Most modern WAFs support this with conditional rules.
Step 3: Per-rule false-positive tuning
For each rule that fires above a threshold, look at samples of what triggered it. Common patterns:
- Customer names with apostrophes triggering SQL injection. Add an exception for that field.
- Base64 image uploads triggering XSS rules because the bytes happen to look like script tags. Skip XSS on multipart bodies.
- Markdown content with code blocks triggering generic injection patterns. Adjust scoring on user-content fields.
- API keys with specific prefixes triggering shell-injection patterns because they happen to contain shell-special characters. Add a pattern exception.
Step 4: Build custom rules for your actual threat model
What attackers do against your specific application is rarely covered by the OWASP CRS. We have written custom rules for clients to detect things like: enumeration of /api/v1/users/{id} where the response status is consistently 200 and the request rate is over 100/min from a single IP; auth-bypass attempts where the JWT signature header is malformed but the request still proceeds; subdomain takeover scanners that follow a specific pattern across paths.
Custom rules are higher signal because they are specific to your shape. They are also more work, because you have to write and maintain them. But they catch attacks that no off-the-shelf rule will.
Step 5: Tune the response action
Default WAF action is block with 403. For high-confidence rules this is correct. For lower-confidence rules, block is overkill and creates user-facing breakage when there is a false positive. Better options for lower confidence:
- Challenge: serve a CAPTCHA. Stops automated attacks, lets humans through.
- Rate limit: throttle to 1 request per second. Slows attackers without blocking outright.
- Log only: alert internal SOC, do not affect the request. Useful for new rules during validation.
- Tarpit: respond very slowly (5+ seconds). Effective against scanners that timeout, transparent to a real user.
What good looks like
After tuning, a typical client's WAF block rate drops from 50K/day to 200-2000/day. Of those, the false-positive rate is below 5 percent, and the SOC team reviews every block from a privileged endpoint. The alerts that do fire are actionable. The dashboard does not look impressive anymore. The actual security posture is dramatically better.
Closing
WAF dashboards optimised for big numbers are optimised for the wrong thing. A WAF that blocks 50,000 false positives a day is doing nothing useful. A WAF that blocks 200 real attacks is doing the job. The work to get from the first to the second is unglamorous detection engineering, but the difference between a tuned and untuned WAF is roughly the same as the difference between having one and not.
Read more field notes, explore our services, or get in touch at info@bipi.in. Privacy Policy · Terms.