Azure Application Gateway WAF – Rule 930120 (OS File Access Attempt) exclusion not working for JSON body key, even after confirming policy binding

Hannah Hsiung (熊偲涵) 0 Reputation points
2026-07-16T06:40:58.8+00:00

Environment

  • Azure Application Gateway v2, WAF_v2 SKU
  • WAF Policy: Managed Rules, Microsoft_DefaultRuleSet version 2.1
  • Backend: Keycloak Admin Console (/admin/realms/{realm}/ui-ext endpoint), request body is application/json
  • Diagnostic logs via AGWFirewallLog (Log Analytics)

The problem

Keycloak's realm settings API sends a JSON payload that includes:

json

"clientProfiles": { "profiles": [] }

This is a legitimate, Keycloak-generated field (an empty array), but it triggers:

930120 – OS File Access Attempt

Pattern match from file lfi-os-files.data at ARGS_NAMES.
{.profile found within [ARGS_NAMES:clientProfiles.profiles]}

The rule is matching on the substring .profile inside the flattened JSON key name (clientProfiles.profiles), not the value — a clear false positive, since the value itself is just [].

What I've tried (exclusions don't take effect)

Configured Managed Rule Exclusions scoped specifically to rule 930120, match variable Request Arg Names — tried every combination below, all in the portal, none stopped the block:

Operator Selector
Contains clientProfiles
-------- --------
Contains clientProfiles
Contains profile
Contains Profile
Contains profiles
StartsWith clientProfiles
Equals clientProfiles.profiles

Ruling out the usual suspects

  • Confirmed the WAF Policy being edited is the one actually enforcing traffic on this listener (log PolicyId matches).
  • Confirmed provisioningState: Succeeded after each change, and waited several minutes for propagation each time.
  • Confirmed it's not an anomaly-score threshold issue — the blocked request's log only lists 930120 as the triggering rule, nothing else contributing to the score.
  • Proved the policy itself is correctly bound and does take effect: added a Custom Rule with Action: Allow matching RequestUri Contains /kcs/admin/realms/.../ui-ext — this immediately let the traffic through. So the Managed Rule Exclusion mechanism itself is what's failing to match, not the policy/listener binding.

This matches other reports of Azure WAF Managed Rule Exclusions silently failing to bind against RequestArgNames derived from flattened/nested JSON body keys.

Questions for the community

  1. Has anyone gotten a Request Arg Names exclusion to actually work against a flattened nested-JSON key like clientProfiles.profiles? Any operator/selector combination that worked for you?
  2. Is there a known issue/bug tracking Managed Rule Exclusions not applying to JSON-derived ARGS_NAMES specifically for rule 930120 (or the LFI rule group in general) on Application Gateway DRS 2.1?
  3. Given the 40-exclusion cap per Application Gateway, is setting the rule's Action to Log (instead of contributing to anomaly score/blocking) the recommended path here, or is there a cleaner fix?

Current workaround under consideration

Since exclusions aren't taking effect, planning to set 930120's Action to Log at the rule level rather than continuing to burn exclusion slots, or allow-listing the whole URI via a Custom Rule (which would drop all WAF coverage for the endpoint). Open to better suggestions.

Happy to share the full JSON payload / diagnostic log export if useful.Environment

Azure Web Application Firewall
0 comments No comments

1 answer

Sort by: Oldest
  1. AI answer

    2026-07-16T06:41:28.27+00:00

    For this case, a managed-rule exclusion is unlikely to fix it.

    The log shows the match is on ARGS_NAMES:clientProfiles.profiles, which means the argument name itself triggered rule 930120, not the JSON value. The documented exclusion mapping for Application Gateway supports ARGS_NAMES:argname to RequestArgNames, and for JSON body fields surfaced as ARGS:fieldname, the guidance is to use RequestArgNames or RequestArgValues rather than RequestBodyPostArgValues.

    That means the technically correct exclusion target for this event is RequestArgNames with selector clientProfiles.profiles. Since that exact approach was already tried and the request still blocks, the supported conclusion from the available guidance is:

    1. The exclusion is either not matching the correct selector as surfaced by the log, or
    2. Another mitigation is required for this rule/path.

    Supported next steps:

    1. Recheck the WAF log entry and use the exact field shown in details_data_s as the selector.
      • For this event, that is clientProfiles.profiles.
      • Use RequestArgNames as the match variable.
      • Prefer Equals for the selector match operator when the field name is exact.
    2. Retest after waiting for propagation.
      • WAF exclusion changes can take 30–60 seconds to propagate.
      • If testing immediately after the change, wait 1–2 minutes and retry.
    3. If the same ruleId_s (930120) still appears after using the exact selector, treat the exclusion as ineffective for this scenario and use a different mitigation.
    4. Use one of the documented alternatives when exclusions cannot be created or do not resolve the false positive:
      • Change the rule action to Log instead of contributing to blocking.
      • Disable the specific rule if acceptable for the risk posture.
      • Create a custom rule that explicitly allows those requests. This bypasses WAF inspection for matching requests, so it is broader and carries more security risk than a targeted managed-rule exclusion.

    For the options under consideration:

    • Set rule 930120 action to Log: this is the cleaner fallback from the provided guidance when a false positive cannot be handled with exclusions.
    • Custom allow rule on the URI: this works, but it is broader because matching requests bypass all WAF inspection.

    No supported material here confirms a known product bug specific to 930120, DRS 2.1, or nested JSON-derived ARGS_NAMES on Application Gateway. No supported material here confirms the 40-exclusion limit question either.


    References:

    AI-generated content may be incorrect. Read our transparency notes for more information.

    Was this answer helpful?

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.