This check flags Azure Application Gateway WAFs running in Detection mode, which logs malicious requests but never blocks them. If your WAF is the line of defense for a public app, switch it to Prevention mode so it actually stops SQL injection, XSS, and other OWASP attacks instead of just watching them happen.
You deployed an Azure Application Gateway with a Web Application Firewall, ran a few attack simulations, saw the alerts roll in, and called it a day. But there's a catch a lot of teams miss: a WAF in Detection mode doesn't actually protect anything. It watches, logs, and waves the traffic through. This Lensix check, appgateway_wafnotprevention, exists because that gap is far more common than it should be.
What this check detects
The check inspects every Azure Application Gateway WAF policy and firewall configuration in your subscription and reports any that have their mode set to Detection instead of Prevention.
Azure WAF has exactly two operating modes:
- Detection mode evaluates incoming requests against the configured rule set (OWASP Core Rule Set, bot protection, custom rules) and logs any matches. It takes no action. The request continues to your backend untouched.
- Prevention mode evaluates the same rules but blocks or challenges requests that match, returning a 403 and writing a log entry.
So the difference between the two is the entire point of having a WAF. Detection mode is essentially a security camera with no door lock.
Note: Detection mode is genuinely useful, but only as a temporary state. It's the recommended starting point when you first turn on a WAF or a new rule set, because it lets you watch for false positives without breaking real traffic. The problem is when "temporary" quietly becomes "permanent."
Why it matters
The risk here is straightforward but easy to underestimate: you have a security control that gives you the false confidence of protection while providing none.
Picture a typical scenario. Your e-commerce app sits behind an Application Gateway WAF. A scanner or an opportunistic attacker starts probing your login form with SQL injection payloads. In Prevention mode, those requests get a 403 and never reach your backend. In Detection mode, every one of them passes straight through to your application code. The only difference is that you now have a tidy log of the breach as it unfolds.
Common attacks the OWASP Core Rule Set is designed to stop, all of which sail through in Detection mode:
- SQL injection against database-backed forms and APIs
- Cross-site scripting (XSS) in user-supplied input
- Remote code execution and command injection
- Local and remote file inclusion
- HTTP protocol violations and request smuggling
There's a compliance angle too. Frameworks like PCI DSS (requirement 6.4.2) call for a WAF or equivalent control in front of public-facing web apps. An auditor will not accept a WAF that doesn't block anything as meeting that requirement. A Detection-mode WAF can fail an audit even though the resource technically exists.
Warning: The most dangerous part of this misconfiguration is organizational, not technical. Teams often see "WAF: Enabled" on a dashboard and check the box mentally. Nobody goes back to verify the mode. Months later, an incident reveals the WAF was passive the entire time.
How to fix it
The fix is to flip the mode to Prevention. How you do that depends on whether you're using a modern WAF policy (recommended) or the older inline WAF configuration on the gateway itself.
Option 1: Azure Portal
- Go to Web Application Firewall policies in the Azure portal, or open your Application Gateway and select the associated WAF policy.
- Under Policy settings, find the Mode toggle.
- Switch it from Detection to Prevention.
- Confirm the Policy state is Enabled and save.
Option 2: Azure CLI (WAF policy)
If you're using a dedicated WAF policy resource (the recommended approach), update the policy settings directly:
az network application-gateway waf-policy policy-setting update \
--policy-name myWafPolicy \
--resource-group myResourceGroup \
--mode Prevention \
--state Enabled
Verify the change:
az network application-gateway waf-policy show \
--name myWafPolicy \
--resource-group myResourceGroup \
--query "policySettings.mode" -o tsv
Option 3: Azure CLI (legacy inline WAF config)
For older gateways where the WAF lives in the gateway's own configuration rather than a separate policy:
az network application-gateway waf-config set \
--gateway-name myAppGateway \
--resource-group myResourceGroup \
--enabled true \
--firewall-mode Prevention \
--rule-set-type OWASP \
--rule-set-version 3.2
Warning: Switching to Prevention can break legitimate traffic if your rules generate false positives. Before flipping the switch on production, review your WAF logs from Detection mode for a few days, identify any benign requests being matched, and create exclusions or disable the offending rules. Going from passive to blocking without that review can take down a working app.
Option 4: Terraform
If you manage the WAF policy as code, set the mode in your resource definition:
resource "azurerm_web_application_firewall_policy" "main" {
name = "myWafPolicy"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
policy_settings {
enabled = true
mode = "Prevention"
}
managed_rules {
managed_rule_set {
type = "OWASP"
version = "3.2"
}
}
}
Option 5: Bicep
resource wafPolicy 'Microsoft.Network/ApplicationGatewayWebApplicationFirewallPolicies@2023-09-01' = {
name: 'myWafPolicy'
location: location
properties: {
policySettings: {
state: 'Enabled'
mode: 'Prevention'
}
managedRules: {
managedRuleSets: [
{
ruleSetType: 'OWASP'
ruleSetVersion: '3.2'
}
]
}
}
}
Tip: Don't manually test by guessing. Send a known-bad request like curl "https://yourapp.com/?id=1' OR '1'='1" after the change. In Prevention mode you should get an HTTP 403. If you still get a 200, the mode didn't actually take effect, or the request isn't routing through the WAF.
How to prevent it from happening again
Fixing one gateway is easy. Making sure a Detection-mode WAF never quietly ships again takes a bit of guardrail work.
Enforce mode with Azure Policy
Azure Policy can audit or deny WAF policies that aren't in Prevention mode. Use an audit effect first to find existing offenders, then move to deny once you're clean:
{
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/ApplicationGatewayWebApplicationFirewallPolicies"
},
{
"field": "Microsoft.Network/ApplicationGatewayWebApplicationFirewallPolicies/policySettings.mode",
"notEquals": "Prevention"
}
]
},
"then": {
"effect": "deny"
}
}
Assign this at the subscription or management group scope so it covers every team without anyone needing to remember.
Gate it in CI/CD
If you provision infrastructure through pipelines, catch the misconfiguration before it deploys. A simple policy-as-code check with Checkov or a custom OPA rule against your Terraform plan will fail the build when mode isn't set to Prevention:
# Run Checkov against your Terraform during the pipeline
checkov -d ./infra --framework terraform
Tip: Pair the deny policy with a continuous check in Lensix. Azure Policy stops new bad deployments, but configuration can drift through manual portal changes. A scheduled scan catches the gateway someone flipped to Detection during a 2am incident and forgot to flip back.
Best practices
Getting the mode right is the headline, but a WAF is only as good as the rest of its configuration. A few things worth doing alongside:
- Use a dedicated WAF policy, not inline config. WAF policies are the modern model, support per-listener and per-path policies, custom rules, and are far easier to manage as code than the legacy inline configuration.
- Start in Detection, but set a deadline. A short tuning window in Detection mode is the right way to onboard a new app. Put a date on it and a ticket to flip to Prevention so it doesn't drift.
- Keep the rule set current. Run the latest OWASP Core Rule Set version available to your gateway SKU. Older versions miss newer attack patterns.
- Tune exclusions deliberately. When you hit a false positive, prefer a narrow exclusion (a specific field or header) over disabling an entire rule. Blanket rule removal opens holes.
- Send WAF logs to Log Analytics. Even in Prevention mode you want visibility into what's being blocked. Diagnostic logs feed your detections and help with incident investigation.
- Combine with custom rules. Rate limiting and geo or IP restrictions handle threats the managed rules don't, like credential stuffing and volumetric abuse.
A WAF in Detection mode is a smoke detector you've wired to a notepad instead of an alarm. It will tell you the house burned down. It won't stop the fire.
Flip the mode, gate it in policy, and scan for drift. That's the whole job, and it takes minutes compared to the cost of an injection attack that walked right past your firewall.

