Skip to main content
GenioCT

Azure WAF False Positives and the Rules That Break Legitimate Traffic

By GenioCT | | 9 min read
Azure WAF Security Application Gateway

In this article

The CRS rules that trigger most often on real Azure web applications and how to safely exclude false positives.

Every Azure WAF deployment hits the same wall. You enable the OWASP Core Rule Set, flip to prevention mode, and within hours someone reports that file uploads are failing, form submissions are rejected, or an API integration is returning 403s. The WAF is doing exactly what it was told to do. The problem is that legitimate traffic looks a lot like attack traffic when your detection rules are broad enough.

We covered the full methodology for WAF analysis in our WAF analysis methodology guide. This article goes deeper on the specific CRS rules that cause the most false positives in real Azure environments and how to handle each one without disabling protection.

SQL Injection Detection: Rules 942100, 942110, 942130

The 942xxx rule family is the single biggest source of false positives we see across client environments. These rules look for SQL syntax patterns in request bodies, headers, and query strings. The intent is to catch injection attempts like ' OR 1=1-- before they reach your database layer.

The problem is that ordinary application traffic constantly contains fragments that match these patterns. A CMS where users write content containing the word “or” in a sentence. A search field where someone types select a product. A form that accepts Base64-encoded data, which often contains character sequences that resemble SQL operators. An e-commerce site where product descriptions include angle brackets or ampersands. Rule 942130 in particular fires on tautology patterns and is notorious for triggering on completely benign text inputs.

To confirm whether your 942xxx hits are false positives, run this against your Log Analytics workspace:

AzureDiagnostics
| where Category == "ApplicationGatewayFirewallLog"
| where ruleId_s startswith "942"
| where TimeGenerated > ago(7d)
| summarize
    HitCount = count(),
    DistinctSources = dcount(clientIp_s),
    SampleURIs = make_set(requestUri_s, 5)
  by ruleId_s, details_data_s
| order by HitCount desc
| take 20

The details_data_s field shows which part of the request triggered the rule. If you see your content submission endpoint appearing hundreds of times with the matched data being normal text, you have a confirmed false positive.

The safe fix is a scoped exclusion that exempts only the specific field on the specific endpoint. For a CMS content field triggering 942130:

{
  "matchVariable": "RequestBodyPostArgNames",
  "selectorMatchOperator": "Equals",
  "selector": "content",
  "exclusionManagedRuleSets": [
    {
      "ruleSetType": "OWASP",
      "ruleSetVersion": "3.2",
      "ruleGroups": [
        {
          "ruleGroupName": "REQUEST-942-APPLICATION-ATTACK-SQLI",
          "rules": [
            { "ruleId": "942100" },
            { "ruleId": "942110" },
            { "ruleId": "942130" }
          ]
        }
      ]
    }
  ]
}

After applying, monitor the excluded field for two weeks. If that endpoint genuinely receives user-generated content, consider adding application-level input validation as a compensating control. The WAF exclusion means that field is no longer inspected for SQL injection. Your application code should pick up the slack with parameterised queries and output encoding.

XSS Detection: Rules 941100, 941110

The 941xxx rules detect cross-site scripting by looking for HTML tags, JavaScript event handlers, and script-like patterns in request data. If your application has a rich text editor, a WYSIWYG content field, or any endpoint that legitimately accepts HTML markup, these rules will fire constantly.

We have seen this in every CMS deployment, every ticketing system with formatted descriptions, and every internal tool that lets users paste HTML snippets. The WAF sees <div class="highlight"> and interprets it the same way it would interpret <script>alert(1)</script>.

Confirm the pattern:

AzureDiagnostics
| where Category == "ApplicationGatewayFirewallLog"
| where ruleId_s in ("941100", "941110")
| where TimeGenerated > ago(7d)
| project TimeGenerated, clientIp_s, requestUri_s, details_data_s, details_msg_s
| order by TimeGenerated desc
| take 50

Look at the details_data_s column. If the matched content is HTML formatting from a known rich text field, it is a false positive. If you see actual script injection attempts mixed in, you have both real attacks and false positives hitting the same rule, which requires more careful scoping.

The exclusion should target only the specific form field that accepts HTML input:

{
  "matchVariable": "RequestBodyPostArgNames",
  "selectorMatchOperator": "Equals",
  "selector": "description",
  "exclusionManagedRuleSets": [
    {
      "ruleSetType": "OWASP",
      "ruleSetVersion": "3.2",
      "ruleGroups": [
        {
          "ruleGroupName": "REQUEST-941-APPLICATION-ATTACK-XSS",
          "rules": [
            { "ruleId": "941100" },
            { "ruleId": "941110" }
          ]
        }
      ]
    }
  ]
}

After excluding, verify that your application sanitises HTML input server-side. Libraries like DOMPurify (client) and HtmlSanitizer (.NET) or Bleach (Python) should be stripping dangerous elements before storage. The WAF was your only XSS defence on that field; now you need the application to handle it.

Request Size Limits: Rules 920300, 920311

These rules enforce maximum sizes for request bodies and headers. Rule 920300 checks that the request body exists and doesn’t exceed the configured limit. Rule 920311 checks for multipart request body sizes. The default thresholds in CRS are conservative, and they will reject legitimate traffic in applications that handle file uploads, large form submissions, or chunked API payloads.

A document management system where users upload PDFs. An API that receives large JSON payloads for batch operations. An image upload endpoint. Any of these will hit 920300 or 920311 if the payload exceeds the default limit.

Confirm with:

AzureDiagnostics
| where Category == "ApplicationGatewayFirewallLog"
| where ruleId_s in ("920300", "920311")
| where TimeGenerated > ago(7d)
| summarize
    HitCount = count(),
    SampleURIs = make_set(requestUri_s, 5)
  by ruleId_s, action_s
| order by HitCount desc

For these rules, the fix is usually adjusting the request body size limit in your WAF policy rather than creating an exclusion. Application Gateway WAF v2 supports request body inspection up to 128 KB by default and can be configured up to 2 MB (or disabled for specific endpoints using a per-URI policy override).

If only certain endpoints need larger payloads, use a per-URI WAF policy to raise the limit only where necessary. Raising the global limit opens your entire application to larger attack payloads, which is exactly the kind of blanket change you want to avoid.

Watch for upload endpoints that suddenly accept much larger payloads than before. Set a realistic maximum based on actual usage rather than removing the limit entirely.

Remote File Inclusion: Rule 931130

Rule 931130 detects potential remote file inclusion (RFI) attacks by looking for URL patterns in query parameters and POST data. The rule fires when it sees http:// or https:// followed by what looks like a path traversal or external domain reference.

Any application that passes URLs as parameters will trigger this rule. A redirect URL in an OAuth flow. A webhook configuration endpoint where users submit callback URLs. An integration that stores external resource URLs. A search feature that accepts URLs as input. All legitimate, all flagged.

Confirm:

AzureDiagnostics
| where Category == "ApplicationGatewayFirewallLog"
| where ruleId_s == "931130"
| where TimeGenerated > ago(7d)
| project TimeGenerated, clientIp_s, requestUri_s, details_data_s
| order by TimeGenerated desc
| take 30

If the details_data_s shows URLs pointing to known domains (your own domain, a configured OAuth provider, a partner API), it is a false positive. If it shows URLs pointing to suspicious external hosts, investigate further.

Scope the exclusion to the specific parameter that carries URLs:

{
  "matchVariable": "RequestArgNames",
  "selectorMatchOperator": "Equals",
  "selector": "redirect_uri",
  "exclusionManagedRuleSets": [
    {
      "ruleSetType": "OWASP",
      "ruleSetVersion": "3.2",
      "ruleGroups": [
        {
          "ruleGroupName": "REQUEST-931-APPLICATION-ATTACK-RFI",
          "rules": [{ "ruleId": "931130" }]
        }
      ]
    }
  ]
}

After excluding, make sure the application validates URL parameters against an allowlist of permitted domains. An open redirect vulnerability combined with a WAF exclusion on the redirect parameter is a real security gap.

SQL Meta Character Detection: Rule 942260

Rule 942260 catches SQL injection attempts that use meta characters and encoding tricks. It fires on payloads containing sequences like ||, &&, backticks, and various encoded forms of SQL operators. JSON payloads with special characters are a frequent trigger because JSON syntax itself uses characters that look like SQL meta operators.

APIs that receive JSON request bodies are the usual victims. A payload like {"filter": "status == 'active' || role == 'admin'"} can trip this rule even though it is standard application logic. Encoded payloads, URL-encoded values, and anything with nested quotes or pipe characters will also match.

Confirm:

AzureDiagnostics
| where Category == "ApplicationGatewayFirewallLog"
| where ruleId_s == "942260"
| where TimeGenerated > ago(7d)
| summarize
    HitCount = count(),
    SampleData = make_set(details_data_s, 5)
  by requestUri_s
| order by HitCount desc
| take 20

For API endpoints, the exclusion typically targets the request body content type:

{
  "matchVariable": "RequestBodyJsonArgNames",
  "selectorMatchOperator": "Equals",
  "selector": "filter",
  "exclusionManagedRuleSets": [
    {
      "ruleSetType": "OWASP",
      "ruleSetVersion": "3.2",
      "ruleGroups": [
        {
          "ruleGroupName": "REQUEST-942-APPLICATION-ATTACK-SQLI",
          "rules": [{ "ruleId": "942260" }]
        }
      ]
    }
  ]
}

After this exclusion, the filter JSON field on that endpoint is no longer inspected for SQL meta characters. If the application uses that field to construct database queries, you absolutely need parameterised queries and input validation at the application layer. The WAF was your safety net; without it, the application code is the only thing between that input and your database.

Before You Disable a Rule

Every exclusion weakens your WAF for that specific scope. Before applying any exclusion, run through this checklist:

  1. Confirm the false positive with data. Run the KQL queries above. Look at actual request samples. “It’s probably a false positive” is not good enough. You need to see the matched data and confirm it is legitimate traffic from expected sources.

  2. Scope the exclusion as narrowly as possible. Exclude one field, for one rule, on one endpoint. Never disable an entire rule group because one endpoint has a problem. Never use wildcard selectors when a specific field name works.

  3. Verify a compensating control exists. If you exclude SQL injection checks on a form field, that field must have parameterised query handling in the application. If you exclude XSS checks on a content field, the application must sanitise HTML. Document which compensating control covers the excluded scope.

  4. Put the exclusion in code, not in the portal. Terraform, Bicep, or ARM template. With a comment explaining why the exclusion exists, what traffic pattern it addresses, and when it was last reviewed. Portal-only exclusions are invisible to future maintainers.

  5. Set a review date. Every exclusion should be revisited at least once per CRS version upgrade. When Microsoft releases a new CRS version, the rule behaviour may change. An exclusion that was necessary under CRS 3.2 might not be needed under 3.3 if the rule was refined.

  6. Monitor after applying. Watch the excluded scope for two weeks. Check whether the exclusion resolved the false positive without introducing new undetected traffic patterns. If the endpoint’s threat profile changes (new features, new user input fields), re-evaluate.

A well-tuned WAF has exclusions. A neglected WAF has disabled rules. The difference is documentation, scoping, and review discipline.

Related: Why Every Azure Enterprise Needs a WAF Analysis Methodology full five-phase tuning process · APIM vs Front Door vs Application Gateway choosing the right edge service · Your Board Is Asking About NIS2 regulatory context for WAF decisions

Need help with your Azure security posture?

We help enterprises design and tune Azure security controls: WAF policies, Sentinel ingestion, Defender for Cloud, identity governance, and NIS2/DORA readiness.

Start with a security assessment. Typical engagement: 2-4 weeks.
Discuss your security needs
Share this article

Start with a Platform Health Check

Not sure where to begin? A quick architecture review gives you a clear picture. No obligation.

  • Risk scorecard across identity, network, governance, and security
  • Top 10 issues ranked by impact and effort
  • 30-60-90 day roadmap with quick wins