Can I limit JSON / XML nesting depth?
Short answer
Yes. The JSON Depth and XML Depth fields in the common rule of the JSON and Xml tabs restrict the nesting level of the deepest value in the body. In JSON, every object and every array around the value counts as one level: 2 for {"a":{"b":1}}, 3 for {"a":[{"b":1}]}. In XML, every element is one level; attributes and elements repeated with the same name each add one more level. Exceeding the limit is a 24-point violation in the Structure Limits category and depends on the Structure Checks switch in the Checks window. The Any Paths default is at most 64 for JSON and at most 128 for XML. Path Depth is a separate field and limits the number of / in the path.
Problem: Requests Arrive with Excessively Nested Bodies
Very deeply nested JSON or XML bodies can be used to cause a stack overflow or high CPU consumption in the application's parser. If the depth the application actually uses is known, deeper bodies are to be rejected.
Solution: Two Methods
The two methods write the same field; one of them is selected.
| Your situation | Suitable method |
|---|---|
| I want to make the setting from the interface | Method 1: Depth field in the common rule |
| I want to do it with a script or the command line | Method 2: WEB-CLI |
Method 1: Depth Field in the Common Rule Recommended
- How it works After the body is parsed, the level of the deepest value is compared with the restriction in the field.
- Where it is opened Left Monitor Panel → WAF-Protected vServices → vService → WAF Management → N page types → rule → JSON / Xml → Add Common Rule for …
- RequirementStructure Checks on
- vService type WAF-enabled HTTP vService
- Measurement examples
{"a":1}→ 1 ·{"a":{"b":1}}→ 2 ·{"a":[{"b":1}]}→ 3 ·<a><b>x</b></a>→ 2 ·<a x="1"/>→ 3
Step-by-Step Configuration
Structure Checks comes on when WAF is turned on; if it has been turned off, in the Left Monitor Panel → WAF-Protected vServices → vService → WAF Management tab, the pencil icon at the top right of the Checks card in the Inspection & Blocking section is clicked (Checks Edit screen).
Structure Checks is set to the on position. While the switch is off, the depth fields are hidden in the form and in the panel.
Edit is clicked.
On the WAF Management tab, the N page types row of the host group is clicked (accessing the Page Types screen).
The row of the page type is clicked in the list; the detail panel of the rule opens on the right (accessing the panel).
The JSON or Xml tab is clicked.
Add Common Rule for JSON (or … for Xml) above the table is clicked; if the rule has its own common rule, the button appears as Edit Common Rule for …. The add form opens filled with the values of the Any Paths rule.
For JSON Depth or XML Depth, the operator and the value are selected (e.g. Less Than or Equal To 6).
Add (Edit when editing) is clicked; the change is applied without a separate deployment step. In a cluster setup, it is also sent to the peer device with the default auto-sync; if Manual Sync Mode is on, it is sent to the peer device manually.
Verification
The JSON depth row in the rule's JSON tab is checked.
≤ 6In Monitor or Blocking mode, a JSON deeper than the limit is sent and the Attacks tab of the Event Logs record is checked.
Attack name: JSON depth; Description: 7>6Method 2: WEB-CLI
- How it works The limit is written to the
--jsonDepthor--xmlDepthfield with WEB-CLI. - Where it is opened WEB-CLI →
waf rule-parts - Requirement WEB-CLI access; Structure Checks on (
waf options update poolId <vService> --syncWithDefaultFwRules false --structureChecks true) - vService type WAF-enabled HTTP vService
- Pre-fill difference
addwrites the command's defaults to the fields that are not written (jsonDepth≤ 8,xmlDepth≤ 32,…BlockAllon,valueLength0–1024)
Step-by-Step Configuration
The ID of the default host group is defaultHost; rule IDs are listed in the id column:
waf fw-rules list poolId <vService> hostGroupId defaultHostThe row that shows json: (all keys) in the description column is the JSON common part:
waf rule-parts list poolId <vService> hostGroupId defaultHost ruleId <rule>waf rule-parts update poolId <vService> hostGroupId defaultHost ruleId <rule> id <part> --jsonDepth.op "<=" --jsonDepth.val 6So that not all JSON bodies are blocked, --jsonBlockAll false is given:
waf rule-parts add poolId <vService> hostGroupId defaultHost ruleId <rule> loc json --jsonBlockAll false --jsonDepth.op "<=" --jsonDepth.val 6Verification
The part is displayed again.
Command: waf rule-parts show poolId <vService> hostGroupId defaultHost ruleId <rule> <part>
The new value in the jsonDepth.op and jsonDepth.val linesCommon Mistakes
- Not counting arrays as levels. In JSON, every array is also a level; in APIs that carry arrays of objects, the limit is chosen accordingly.
- Not taking the effect of attributes and repeated elements in XML into account. Attribute values and elements repeated with the same name each increase the measurement by one level (How are element and attribute paths defined in XML?).
- Expecting a depth measurement on a body that exceeds the processable size. Bodies that exceed the body processing limit are not parsed; what happens to them is determined by Block Unparsed Contents in the Raw tab (What is the difference between Block Unparsed Contents and Block Unexpected Parser Errors?).
- Confusing it with Path Depth. Path Depth limits the number of
/in the path and is the page type's own field (What are the Path Length and Path Depth constraints for?).
How it is done in the documentation
