Skip to content

Commit 5344722

Browse files
[WAF] Custom rulesets at zone level (#26765)
--------- Co-authored-by: Kate Tungusova <70746074+deadlypants1973@users.noreply.github.com>
1 parent c90e21e commit 5344722

File tree

24 files changed

+551
-110
lines changed

24 files changed

+551
-110
lines changed

public/__redirects

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2403,7 +2403,6 @@
24032403
# WAF
24042404
/waf/managed-rulesets/* /waf/managed-rules/:splat 301
24052405
/waf/custom-rulesets/* /waf/account/custom-rulesets/:splat 301
2406-
/waf/custom-rules/custom-rulesets/* /waf/account/custom-rulesets/:splat 301
24072406
/waf/exposed-credentials-check/* /waf/managed-rules/check-for-exposed-credentials/:splat 301
24082407
/waf/security-events/* /waf/analytics/security-events/:splat 301
24092408
/waf/change-log/2019-* /waf/change-log/historical-2019/ 301

src/content/docs/bots/concepts/feedback-loop.mdx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ If Cloudflare is unable to detect a portion of automated traffic on your site, s
4141

4242
## Submit a report
4343

44-
<Tabs syncKey="dashNewNav">
44+
<Tabs syncKey="dashNewNav">
4545
<TabItem label="Old dashboard">
4646
<Steps>
4747
1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/), and select your account and domain.
@@ -50,7 +50,7 @@ If Cloudflare is unable to detect a portion of automated traffic on your site, s
5050
4. Select **Report incorrect data** and fill out the form.
5151
5. Select **Submit**.
5252
</Steps>
53-
</TabItem>
53+
</TabItem>
5454
<TabItem label="New dashboard" icon="rocket">
5555
<Steps>
5656
1. In the Cloudflare dashboard, go to the **Security Analytics** page.
@@ -61,7 +61,7 @@ If Cloudflare is unable to detect a portion of automated traffic on your site, s
6161
4. Select **Report incorrect data** and fill out the form.
6262
5. Select **Submit**.
6363
</Steps>
64-
</TabItem>
64+
</TabItem>
6565
</Tabs>
6666

6767
## Via the API
@@ -224,17 +224,15 @@ We appreciate any comments you wish to leave in the description field that might
224224
## Recommendations after submitting a false positive
225225

226226
:::note
227-
228-
The instructions below apply to Enterprise subscription with Bot Management only.
227+
The instructions below apply to Enterprise subscription with Bot Management only.
229228
:::
230229

231-
After submitting a false positive, you can explicitly allow the traffic if you are confident that this traffic source cannot be used for abuse in the future. To allow traffic, you can create a WAF custom rule with a [Skip the remaining custom rules](/waf/custom-rules/skip/options/) action that matches the characteristics of your false positive report. We recommend any skip rule that you create uses the most narrow possible scope, including restricting the request methods and URIs that the expected traffic has access to, to limit potential abuse.
230+
After submitting a false positive, you can explicitly allow the traffic if you are confident that this traffic source cannot be used for abuse in the future. To allow traffic, you can create a WAF custom rule with a [Skip the remaining custom rules](/waf/custom-rules/skip/options/#skip-the-remaining-custom-rules-current-ruleset) action that matches the characteristics of your false positive report. We recommend any skip rule that you create uses the most narrow possible scope, including restricting the request methods and URIs that the expected traffic has access to, to limit potential abuse.
232231

233232
* Allowing a **[JA3/JA4 fingerprint](/bots/additional-configurations/ja3-ja4-fingerprint/)**: If you want to allow access to a stable software client that does not come from a dedicated IP, you can do so by looking up the JA3 fingerprint(s) used by that client in the Bot Analytics dashboard, and creating a WAF custom rule to allow traffic based on that JA3 fingerprint. JA3 fingerprints will only match a client’s TLS library, so be cautious in looking for both overlap with other clients and with variation based on the operating system. <br/><br/>Cloudflare does not recommend relying on JA3 rules for mobile applications that may be abused. If you have questions about how to securely allow traffic from your mobile application, please contact your account team.
234233

235234
:::note
236-
237-
The instructions below apply to Enterprise subscription with Bot Management, Bot Fight Mode and Super Bot Fight Mode.
235+
The instructions below apply to Enterprise subscription with Bot Management, Bot Fight Mode and Super Bot Fight Mode.
238236
:::
239237

240238
* Allowing an **IP address**: Only use an IP address to allow traffic if the IP is a dedicated resource that belongs only to the traffic source you wish to allow. <br/>If the traffic you want to allow shares an IP with other traffic sources, or if the IP changes frequently, consider an alternative to allowing by IP address.

src/content/docs/ruleset-engine/about/phases.mdx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@ sidebar:
77

88
A phase defines a stage in the life of a request where you can execute [rulesets](/ruleset-engine/about/rulesets/). Phases are defined by Cloudflare and cannot be modified.
99

10-
Phases exist at two levels: at the account level and at the zone level. For the same phase, rules defined at the account level are evaluated before the rules defined at the zone level.
10+
Phases exist at two levels:
11+
12+
- At the [account](/fundamentals/concepts/accounts-and-zones/#accounts) level
13+
- At the [zone](/fundamentals/concepts/accounts-and-zones/#zones) level
14+
15+
For the same phase, rules defined at the account level are evaluated before the rules defined at the zone level.
1116

1217
Each phase has at most one [entry point ruleset](/ruleset-engine/about/rulesets/#entry-point-ruleset) at the account and zone level.
1318

src/content/docs/ruleset-engine/basic-operations/add-rule-phase-rulesets.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ A [phase entry point ruleset](/ruleset-engine/about/rulesets/#entry-point-rulese
1212

1313
To add one or more rules to a phase entry point ruleset, use one of the [ruleset update operations](/ruleset-engine/rulesets-api/update/) of the [Rulesets API](/ruleset-engine/rulesets-api/). When you add a rule to an entry point ruleset, the entry point ruleset is created automatically if it does not exist. This API method requires that you include in the request all rules you want to keep in the ruleset, or else they will be removed.
1414

15-
If you are adding a **single** rule to a ruleset, consider using one of the [rule creation operations](/ruleset-engine/rulesets-api/add-rule/) instead. In this case, the request will only include the definition of the new rule.
15+
If you are adding a single rule to a ruleset, consider using one of the [rule creation operations](/ruleset-engine/rulesets-api/add-rule/) instead. In this case, the request only includes the definition of the new rule.
1616

1717
:::note[Creating an entry point ruleset]
1818
Instead of relying on the automatic creation of an entry point ruleset, you can also create this ruleset explicitly using one of the [ruleset creation operations](/ruleset-engine/rulesets-api/create/).

src/content/docs/ruleset-engine/custom-rulesets/add-rules-ruleset.mdx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@ sidebar:
77

88
import { APIRequest, Render } from "~/components";
99

10-
To add rules to an existing custom ruleset, use the [Update an account ruleset](/api/resources/rulesets/methods/update/) operation and pass the rules in an array. Each rule has an expression and an action.
10+
To add rules to an existing custom ruleset, use the [Update an account or zone ruleset](/api/resources/rulesets/methods/update/) operation and pass the rules in an array. Each rule has an expression and an action.
1111

1212
:::note[Choosing the appropriate API method]
1313

14-
When you add rules to a custom ruleset using the [Update an account ruleset](/api/resources/rulesets/methods/update/) operation, you replace all the rules in the ruleset with the rules in the request. Use this API method when adding or updating several rules at once. This method will update the ruleset version number only once.
14+
When you add rules to a custom ruleset using the [Update an account or zone ruleset](/api/resources/rulesets/methods/update/) operation, you replace all the rules in the ruleset with the rules in the request. Use this API method when adding or updating several rules at once. This method will update the ruleset version number only once.
1515

1616
You can use other API operations depending on the type of operation:
1717

18-
- Add a single rule to an existing custom ruleset: Use the [Create an account ruleset rule](/api/resources/rulesets/subresources/rules/methods/create/) operation.
19-
- Update a single rule in a custom ruleset: Use the [Update an account ruleset rule](/api/resources/rulesets/subresources/rules/methods/edit/) operation.
18+
- Add a single rule to an existing custom ruleset: Use the [Create an account or zone ruleset rule](/api/resources/rulesets/subresources/rules/methods/create/) operation.
19+
- Update a single rule in a custom ruleset: Use the [Update an account or zone ruleset rule](/api/resources/rulesets/subresources/rules/methods/edit/) operation.
2020

2121
:::
2222

@@ -26,7 +26,7 @@ You can use other API operations depending on the type of operation:
2626

2727
## Add rules
2828

29-
The following request adds two rules to a custom ruleset with ID `$RULESET_ID`. These will be the only two rules in the ruleset.
29+
The following request adds two rules to a custom ruleset at the account level with ID `$RULESET_ID`. These will be the only two rules in the ruleset.
3030

3131
The response will include the rule ID of the new rules in the `id` field.
3232

@@ -90,9 +90,9 @@ The response will include the rule ID of the new rules in the `id` field.
9090

9191
## Update rules
9292

93-
To update one or more rules in a custom ruleset, use the [Update an account ruleset](/api/resources/rulesets/methods/update/) operation. Include the ID of the rules you want to modify in the rules array and add the fields you wish to update. The request replaces the entire ruleset with a new version. Therefore, you must include the ID of all the rules you wish to keep.
93+
To update one or more rules in a custom ruleset, use the [Update an account or zone ruleset](/api/resources/rulesets/methods/update/) operation. Include the ID of the rules you want to modify in the rules array and add the fields you wish to update. The request replaces the entire ruleset with a new version. Therefore, you must include the ID of all the rules you wish to keep.
9494

95-
The following `PUT` request edits one rule in a custom ruleset and updates the execution order of the rules.
95+
The following `PUT` request edits one rule in a custom ruleset at the account level and updates the execution order of the rules.
9696

9797
The response will include the modified custom ruleset. Note that the updated rule and ruleset version number increment.
9898

src/content/docs/ruleset-engine/custom-rulesets/create-custom-ruleset.mdx

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ sidebar:
77

88
import { APIRequest, Render } from "~/components";
99

10-
Use the [Create an account ruleset](/api/resources/rulesets/methods/create/) operation to create a custom ruleset, making sure that you:
10+
Use the [Create an account or zone ruleset](/api/resources/rulesets/methods/create/) operation to create a custom ruleset, making sure that you:
1111

1212
- Set the `kind` field to `custom`.
1313
- Specify the name of the [phase](/ruleset-engine/reference/phases-list/) where you want to create the custom ruleset in the `phase` field.
@@ -16,16 +16,53 @@ Use the [Create an account ruleset](/api/resources/rulesets/methods/create/) ope
1616

1717
<Render file="custom-rulesets-dashboard" product="ruleset-engine" />
1818

19-
## Example
19+
<Render file="custom-ruleset-zone-limitation" product="ruleset-engine" />
2020

21-
The following request creates a new custom ruleset. The response will include the ID of the new custom ruleset in the `id` field.
21+
## Example A - Custom ruleset at the account level
22+
23+
The following request creates a new custom ruleset at the account level. The response will include the ID of the new custom ruleset in the `id` field.
2224

2325
<APIRequest
2426
path="/accounts/{account_id}/rulesets"
2527
method="POST"
2628
json={{
2729
name: "Custom Ruleset 1",
28-
description: "My First Custom Ruleset",
30+
description: "My First Custom Ruleset (account)",
31+
kind: "custom",
32+
phase: "http_request_firewall_custom",
33+
}}
34+
/>
35+
36+
```json output {3}
37+
{
38+
"result": {
39+
"id": "f82ccda3d21f4a02825d3fe45b5e1c10",
40+
"name": "Custom Ruleset 1",
41+
"description": "My First Custom Ruleset (account)",
42+
"kind": "custom",
43+
"version": "1",
44+
"last_updated": "2025-08-09T10:27:30.636197Z",
45+
"phase": "http_request_firewall_custom"
46+
},
47+
"success": true,
48+
"errors": [],
49+
"messages": []
50+
}
51+
```
52+
53+
You can include a list of rules in the custom ruleset creation request. If you have not added any rules, refer to [Add rules to a custom ruleset](/ruleset-engine/custom-rulesets/add-rules-ruleset/) for more information.
54+
55+
56+
## Example B - Custom ruleset at the zone level
57+
58+
The following request creates a new custom ruleset at the zone level. The response will include the ID of the new custom ruleset in the `id` field.
59+
60+
<APIRequest
61+
path="/zones/{zone_id}/rulesets"
62+
method="POST"
63+
json={{
64+
name: "Custom Ruleset 1",
65+
description: "My First Custom Ruleset (zone)",
2966
kind: "custom",
3067
phase: "http_request_firewall_custom",
3168
}}
@@ -36,10 +73,10 @@ The following request creates a new custom ruleset. The response will include th
3673
"result": {
3774
"id": "f82ccda3d21f4a02825d3fe45b5e1c10",
3875
"name": "Custom Ruleset 1",
39-
"description": "My First Custom Ruleset",
76+
"description": "My First Custom Ruleset (zone)",
4077
"kind": "custom",
4178
"version": "1",
42-
"last_updated": "2021-03-09T10:27:30.636197Z",
79+
"last_updated": "2025-08-09T10:27:30.636197Z",
4380
"phase": "http_request_firewall_custom"
4481
},
4582
"success": true,
@@ -49,3 +86,6 @@ The following request creates a new custom ruleset. The response will include th
4986
```
5087

5188
You can include a list of rules in the custom ruleset creation request. If you have not added any rules, refer to [Add rules to a custom ruleset](/ruleset-engine/custom-rulesets/add-rules-ruleset/) for more information.
89+
90+
<Render file="custom-ruleset-zone-limitation" product="ruleset-engine" />
91+

src/content/docs/ruleset-engine/custom-rulesets/deploy-custom-ruleset.mdx

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,27 @@ description: Learn how to deploy a custom ruleset to your Cloudflare account.
88

99
import { APIRequest, Render } from "~/components";
1010

11-
To deploy a custom ruleset, add a rule with `execute` action to the list of rules of a phase [entry point ruleset](/ruleset-engine/about/rulesets/#entry-point-ruleset) at the account level. The expression of the new rule will define when the custom ruleset will run.
11+
To deploy a custom ruleset, add a rule with `execute` action to the list of rules of a phase [entry point ruleset](/ruleset-engine/about/rulesets/#entry-point-ruleset) at the account or zone level. The expression of the new rule will define when the custom ruleset will run.
12+
13+
You can only deploy custom rulesets in an entry point ruleset with the same scope. For example, a custom ruleset defined at the account level can only be deployed at the account level.
1214

1315
<Render file="custom-rulesets-terraform" product="ruleset-engine" />
1416

1517
<Render file="custom-rulesets-dashboard" product="ruleset-engine" />
1618

19+
<Render file="custom-ruleset-zone-limitation" product="ruleset-engine" />
20+
1721
## Before you begin
1822

1923
1. Obtain the name of the [phase](/ruleset-engine/reference/phases-list/) where you want to deploy the custom ruleset.
2024
2. [Create a custom ruleset](/ruleset-engine/custom-rulesets/create-custom-ruleset/) and keep the ID of the new custom ruleset.
2125
3. [Fetch the rules already present in the phase entry point ruleset](/ruleset-engine/basic-operations/view-rulesets/#view-the-rules-included-in-a-ruleset). You must include in the `PUT` request all existing rules you want to keep.
2226

23-
## Example
27+
## Example A - Account-level deployment
2428

25-
The following `PUT` request adds a rule that executes a custom ruleset when the zone name matches `example.com`. The response will include all the rules in the phase entry point ruleset.
29+
The following `PUT` request adds a rule that executes a custom ruleset when the zone name matches `example.com`.
30+
31+
In the `PUT` request, you must include the IDs of all existing rules you want to keep. The response will include all the rules in the phase entry point ruleset after the update.
2632

2733
<APIRequest
2834
path="/accounts/{account_id}/rulesets/phases/{ruleset_phase}/entrypoint"
@@ -110,5 +116,78 @@ The following `PUT` request adds a rule that executes a custom ruleset when the
110116
```
111117

112118
:::caution
113-
Regarding the expression of the rule deploying the ruleset, you must use parentheses to enclose any custom conditions and end your expression with `and cf.zone.plan eq "ENT"` or else the API operation will fail.
119+
When deploying the custom ruleset at the account level, you must use parentheses to enclose any custom conditions and end your expression with `and cf.zone.plan eq "ENT"` like in the example above, or else the API operation will fail.
114120
:::
121+
122+
## Example B - Zone-level deployment
123+
124+
The following `PUT` request adds a rule to a zone-level entry point ruleset that executes a custom ruleset with ID `"<CUSTOM_RULESET_ID>"` for requests targeting the `/login` URI path.
125+
126+
You must include in the `PUT` request the IDs of all existing rules you want to keep. The response will include all the rules in the phase entry point ruleset after the update.
127+
128+
<APIRequest
129+
path="/zones/{zone_id}/rulesets/phases/{ruleset_phase}/entrypoint"
130+
method="PUT"
131+
parameters={{
132+
ruleset_phase: "http_request_firewall_custom",
133+
}}
134+
json={{
135+
rules: [
136+
{
137+
action: "execute",
138+
description: "Execute custom ruleset (zone)",
139+
expression: '(http.request.uri.path eq "/login")',
140+
action_parameters: {
141+
id: "<CUSTOM_RULESET_ID>",
142+
},
143+
},
144+
{
145+
id: "<EXISTING_PHASE_RULE_ID_1>",
146+
},
147+
],
148+
}}
149+
/>
150+
151+
```json output
152+
{
153+
"result": {
154+
"id": "<ZONE_PHASE_RULESET_ID>",
155+
"name": "http_request_firewall_custom phase entry point ruleset for my zone",
156+
"description": "",
157+
"kind": "zone",
158+
"version": "3",
159+
"rules": [
160+
{
161+
"id": "<PHASE_RULE_ID>",
162+
"version": "1",
163+
"action": "execute",
164+
"description": "Execute custom ruleset (zone)",
165+
"action_parameters": {
166+
"id": "<CUSTOM_RULESET_ID>",
167+
"version": "latest"
168+
},
169+
"expression": "(http.request.uri.path eq \"/login\")",
170+
"last_updated": "2025-08-18T18:35:14.135697Z",
171+
"ref": "<PHASE_RULE_REF>",
172+
"enabled": true
173+
},
174+
{
175+
"id": "<EXISTING_PHASE_RULE_ID_1>",
176+
"version": "1",
177+
"action": "managed_challenge",
178+
"expression": "(cf.waf.score lt 20 and http.request.uri.path wildcard \"/admin/*\")",
179+
"last_updated": "2025-08-16T15:51:49.180378Z",
180+
"ref": "<EXISTING_PHASE_RULE_REF_1>",
181+
"enabled": true
182+
}
183+
],
184+
"last_updated": "2025-08-18T18:35:14.135697Z",
185+
"phase": "http_request_firewall_custom"
186+
},
187+
"success": true,
188+
"errors": [],
189+
"messages": []
190+
}
191+
```
192+
193+
<Render file="custom-ruleset-zone-limitation" product="ruleset-engine" />

src/content/docs/ruleset-engine/custom-rulesets/index.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ sidebar:
55
order: 7
66
---
77

8-
Use the following workflow to deploy a custom ruleset at the account level:
8+
Use the following workflow to deploy a custom ruleset:
99

1010
1. [Create a custom ruleset](/ruleset-engine/custom-rulesets/create-custom-ruleset/).
1111
2. [Add rules to your custom ruleset](/ruleset-engine/custom-rulesets/add-rules-ruleset/).
12-
3. [Add a rule to an account-level phase entry point ruleset that executes the custom ruleset](/ruleset-engine/custom-rulesets/deploy-custom-ruleset/).
12+
3. [Add a rule to a phase entry point ruleset that executes the custom ruleset](/ruleset-engine/custom-rulesets/deploy-custom-ruleset/).
1313

1414
You must create a rule with `execute` action in an entry point ruleset to execute the custom ruleset (step 3 in the previous procedure). If you skip this step, the rules of the custom ruleset will not run.
1515

16-
Currently, custom rulesets are only supported by the [Cloudflare WAF](/waf/).
16+
Currently, custom rulesets are only supported by the [Cloudflare WAF](/waf/), both at the account and the zone level.
1717

1818
:::note
1919
You cannot execute a custom ruleset from another custom ruleset, only from an entry point ruleset.

src/content/docs/ruleset-engine/rules-language/actions.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ The available actions depend on the [phase](/ruleset-engine/about/phases/) where
116116
<p>
117117
<ul>
118118
<li>Skip all remaining rules in the current ruleset</li>
119+
<li>Skip all remaining rules in the current phase (zone-level only option)</li>
119120
<li>Skip rulesets</li>
120121
<li>Skip rules of a ruleset</li>
121122
<li>Skip phases</li>

src/content/docs/ruleset-engine/rulesets-api/create.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Use the `rules` parameter to supply a list of rules for the ruleset. For an obje
3939

4040
## Example - Create a custom ruleset
4141

42-
The following `POST` request creates a custom ruleset in the `http_request_firewall_custom` phase containing a single rule.
42+
The following `POST` request creates a custom ruleset in the `http_request_firewall_custom` phase at the account level containing a single rule.
4343

4444
<APIRequest
4545
path="/accounts/{account_id}/rulesets"

0 commit comments

Comments
 (0)