Cloud
Azure WAF: move a policy from Detection to Prevention without breaking traffic
A production runbook for qualifying an Azure WAF policy before switching to Prevention with KQL evidence, change scope, application validation, rollback window and an operable decision.
Moving an Azure WAF policy from Detection to Prevention can look like a simple security toggle. In production, it is an application change. Requests that were only logged can start being blocked, partner integrations can disappear behind 403 responses, and support teams may discover too late that they cannot separate a real block from a false positive.
The use case is an application published behind Application Gateway WAF. The policy has been running in Detection for days or weeks. The team wants to enable Prevention without weakening managed rules, without adding broad exclusions and without turning the first hour into an incident. The runbook goal is to decide whether the switch is ready, how to watch it, what to roll back and which evidence to keep.
Treat the switch as a production change
A policy in Detection is not inactive. It produces an operational simulation of future blocks. The useful question is therefore not only “how many rules matched?”. The useful question is: which legitimate requests would be blocked if the policy actually enforced its decisions?
Change scope
Affected Application Gateway and WAF policy
Published hostnames
Critical paths: login, payment, import, webhook, partner API, callback
Impacted environments
Managed ruleset version and active custom rules
Expected evidence
Top simulated blocks in Detection
Associated ruleId and message
URI, method, hostname, client IP and user agent
Volume by time bucket
Samples of legitimate and illegitimate requests
Decision per case: accept, fix application, targeted exclusion, custom rule, rollback
Switch conditions
Critical false positives handled
Monitoring ready
Support aware of expected symptoms
Rollback documented and tested This intake prevents a common mistake: enabling Prevention because the global match count looks low while one business-critical path contains most requests that will be blocked.
Read Detection logs as a forecast
The first query should isolate what Prevention would block. Depending on ingestion, tables and fields may differ between AzureDiagnostics and dedicated Application Gateway tables. The principle stays the same: period, hostname, URI, action, ruleId, message and number of distinct clients.
let Window = 7d;
AzureDiagnostics
| where TimeGenerated > ago(Window)
| where Category == "ApplicationGatewayFirewallLog"
| extend hostname = tostring(host_s)
| extend uri = tostring(requestUri_s)
| extend method = tostring(requestMethod_s)
| extend action = tostring(action_s)
| extend ruleId = tostring(ruleId_s)
| extend message = tostring(message_s)
| extend clientIp = tostring(clientIp_s)
| where action in ("Matched", "Detected", "Blocked")
| summarize hits=count(),
clients=dcount(clientIp),
firstSeen=min(TimeGenerated),
lastSeen=max(TimeGenerated),
sampleMessages=make_set(message, 3)
by hostname, uri, method, ruleId, action
| order by hits desc A WAF hit is not automatically a false positive. A wave of suspicious requests on /wp-admin may be healthy to block. A SQLi rule on an internal import endpoint may instead reveal a legitimate payload that is poorly encoded, or an API that accepts risky fields too freely. Qualify by use case, not by volume only.
Build a decision matrix per path
Before the switch, every critical path needs a decision. The decision may be to do nothing, fix the application, add a targeted exclusion, strengthen a custom rule, or postpone Prevention if evidence is insufficient.
Path: /login
WAF signal: brute force, automation, atypical headers
Business impact: user authentication
Decision: Prevention possible if application errors and support stay normal
Validation: expected 403 rate on suspicious sources, not on legitimate cohorts
Rollback: return policy to Detection if legitimate users are blocked
Path: /api/import
WAF signal: ruleId on JSON or multipart content
Business impact: partner integration or critical batch
Decision: replay representative payloads before Prevention
Validation: WAF correlation plus application logs plus partner response
Rollback: Detection or targeted exclusion with expiration
Path: /webhook/provider
WAF signal: unusual user agent or signature
Business impact: asynchronous inbound events
Decision: verify source IPs, signatures and provider retries
Validation: no backlog, no event loss
Rollback: Detection if backlog or retries rise after switch This matrix makes the change window shorter. The team does not debate WAF severity in the abstract. It decides path by path with a signal and a return path.
Prepare probes and correlation
On the switch day, application probes and KQL queries should already be ready. A probe that only checks the home page is not enough if the risks sit on login, import, webhook or partner API paths.
Before switch
Replay critical journeys from a network close to users
Verify representative payloads for sensitive endpoints
Add a correlation ID when the application supports it
Confirm that Application Gateway, WAF and application logs arrive
During switch
Watch 403, 502, latency and application errors
Compare affected paths with expected paths
Read WAF ruleId before adding an exception
Keep a support channel open for first reports
After switch
Capture before and after on the same time window
Identify remaining false positives
Remove useless temporary exceptions
Document the final decision Correlation matters more than the raw number of 403s. More 403s on automated sources can be the expected result. A few 403s on a critical internal client can justify immediate rollback.
Watch Prevention before tickets arrive
After activation, the monitoring query should separate expected blocks from new blocks. It should also show whether one hostname or path suddenly concentrates the risk.
let ChangeTime = datetime(2026-06-20T08:00:00Z);
let Window = 2h;
AzureDiagnostics
| where TimeGenerated between (ChangeTime .. ChangeTime + Window)
| where Category == "ApplicationGatewayFirewallLog"
| extend hostname = tostring(host_s)
| extend uri = tostring(requestUri_s)
| extend method = tostring(requestMethod_s)
| extend action = tostring(action_s)
| extend ruleId = tostring(ruleId_s)
| extend clientIp = tostring(clientIp_s)
| where action has_any ("Blocked", "Prevention")
| summarize blocked=count(),
clients=dcount(clientIp),
firstSeen=min(TimeGenerated),
lastSeen=max(TimeGenerated),
sampleClients=make_set(clientIp, 5)
by hostname, uri, method, ruleId
| order by blocked desc Read this query with application logs. If WAF blocks a request, the application may never see it. Missing application logs are not proof that everything is fine. Conversely, rising application errors without WAF blocks likely point to another deployment problem.
Bound exceptions instead of opening broadly
If a false positive appears after the switch, the fastest response is not always the best one. Returning to Detection may be better than adding a broad exclusion that stays in place. An exclusion should target a ruleId, field, path and duration.
Before exception
RuleId identified
Path and hostname limited
Matched field understood: cookie, header, arg, body, multipart
Legitimate request sample retained
Bypass risk reviewed
Expiration or review planned
Prefer Detection rollback when
The false positive affects a broad critical path
The matched field is not understood
Several different ruleIds appear at once
The team cannot prove legitimate traffic
The required exception would be too global
Prefer targeted exclusion when
The legitimate payload is stable
The ruleId is unique or very limited
The path is constrained
The before and after test is reproducible
Security review accepts the compromise The discipline is simple: if the team cannot explain exactly what is excluded, it is safer to roll back the mode than keep an opaque exception.
Decide rollout, hold or rollback
The change should end with an explicit decision. The worst state is a policy in Prevention with temporary exceptions, open support tickets and no planned review.
Decision: rollout confirmed
Critical probes pass
Blocks match expected paths and sources
No legitimate critical client is blocked
Remaining false positives have a fix or targeted exclusion
Logs can reconstruct the decision
Decision: hold under watch
Prevention stays active but a review is scheduled
Blocks are acceptable but not yet stable
Temporary exceptions have a removal date
Support knows which symptoms to escalate
Decision: rollback to Detection
Critical path blocked without a targeted fix
Backlog, business errors or partner calls fail
RuleId or matched field is not understood
Required exclusion would be too broad
Visibility is lost or logs are insufficient Rollback should be clean: return the policy to Detection, keep logs from the window, annotate affected paths, then add missing payloads or scenarios to the matrix before trying again.
Conclusion
Enabling Azure WAF Prevention is not a checkbox. It is a production change that should start from Detection logs, go through a critical-path matrix, rely on realistic probes and keep immediate rollback available.
The right decision is not always to activate at any cost. It may be to confirm Prevention, hold under watch with targeted exceptions, or return to Detection when evidence is missing. What matters is that blocked traffic is explainable, legitimate traffic remains verified and every exception has a reason, a scope and an exit.