---
schema_version: "1"
id: c07afeebfee80f09c6bfcf3b62c7dd4951ac40aa0ea567797ff695d1d006c714
title: eCDN Custom Rules
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/commerce-cloud/commerce-api/guides/cdn-zones-custom-rules.md
canonical_url: https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/cdn-zones-custom-rules.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: 13fdb33c2060a950341d6aa7a3f5ca082a4c1f745a973cb351d4966f14e96a1d
products:
  - Composable Storefront
  - Salesforce APIs
---
# eCDN Custom Rules

Use custom rules to control incoming traffic by setting up security policies based on request parameters. With custom rules, you have complete control over the rule expression, the allowed request field types, and the rule actions. This flexibility helps you create expressions that match your traffic needs. To create a custom rule in Business Manager, see [Create a Custom Rule for an eCDN Zone](https://help.salesforce.com/s/articleView?id=cc.b2c_create_eCDN_firewall_rule.htm) in _Salesforce Help_.

## Validation Overview

### Rule Expression

See [eCDN Rule Expression Fields](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/cdn-rule-expression-fields.md) for the operators, functions, and fields supported in a custom rule expression. Rate limiting rule expressions use the same list.

**important:** **Challenge actions on SLAS login endpoints:** Don't apply `js_challenge`, `legacy_captcha`, or `managed_challenge` to SLAS login endpoints in a custom rule. SLAS login is API-based, not a browser page, so the endpoint cannot present an interactive challenge. Unless the storefront interprets the challenge response and presents a challenge to the shopper, a Challenge action behaves like a permanent block: a shopper whose credentials appear in a leak has no way to prove they are human and log in. Start the rule with the `log` action. While the rule is in log mode, monitor the traffic that matches it and assess whether those requests are safe to block—or, if the storefront can present a challenge, safe to Challenge.

### Rule Actions

The following rule actions are supported in the actions array:

- `block` - Denies access to the requested site.
- `js_challenge` - The client that made the request must pass a JavaScript Challenge before proceeding.
- `legacy_captcha` - The client that made the request must pass an interactive challenge.

  **note:** Legacy captcha still exist through the API. However, Salesforce recommends selecting the managed challenge response for a better user experience.

- `managed_challenge` - Depending on the characteristics of the request, the appropriate type of challenge is presented to the client.
- `log` - Logs matching requests.

The following skip actions are also supported in the actions array:

- `skip_custom_rules` - Skips all remaining custom rules (meaning custom rules with a lower priority are not evaluated).
- `skip_security_level` - Skips Security Level.
- `skip_rate_limiting_rules` - Skips rate limiting rules. See [eCDN Rate Limiting Rules](https://developer.salesforce.com/docs/commerce/commerce-api/guide/cdn-rate-limiting-rules.html) for related documentation.
- `skip_wafv2` - Skips WAFv2 managed rules. For additional information, see [eCDN WAFv2](https://developer.salesforce.com/docs/commerce/commerce-api/guide/cdn-zones-wafv2.html).

**important:** If using the skip actions, the user can provide multiple skip actions in the array. Otherwise, the array includes only 1 rule action. See the following usage examples:

```json
"actions": ["block"]

"actions": ["skip_custom_rules", "skip_wafv2"]

"actions": ["managed_challenge"]
```

### Rule Order

Custom rules are evaluated in the order they are listed in the response body. If a custom rule’s expression is matched, the action is executed.

- The `managed_challenge`, `js_challenge`, `legacy_captcha`, `block`, and `skip_custom_rules` actions stop further custom rule evaluation and no other rules in the ruleset are evaluated.
- The `skip_security_level`, `skip_rate_limiting_rules`, `skip_wafv2`, and `log` actions do not stop custom rule evaluation.

### Position

When creating or updating a custom rule, users can provide a `position` attribute in the request body to insert the rule at a certain relative position in the ruleset. _If the position is not provided during rule creation, the rule is added to the end of the ruleset by default._ See the following usage examples:

```json
# Places the rule before rule <RULE_ID>

"position": {
   "before": "<RULE_ID>"
}

or

# Places the rule after rule <RULE_ID>

"position": {
   "after": "<RULE_ID>"
}
```

## Examples

The following examples show common custom rules. Combine and adjust them to your own business needs.

- **Challenge non-verified bots hitting the storefront cart endpoint:**
  - Expression: `(http.request.uri.path contains "/Cart-AddProduct" and not cf.client.bot)`
  - Action: `managed_challenge`
- **Allow verified search engines through a country-based block:**
  - Expression: `(ip.src.country in {"CU" "IR"} and not cf.client.bot)`
  - Action: `block`
- **Challenge login requests where the submitted password matches a known leak:**
  - Expression: `(http.request.uri.path contains "/Account-Login" and cf.waf.credential_check.password_leaked)`
  - Action: `managed_challenge`

## Create a Custom Rule

This endpoint creates a custom rule in the specified zone.

- The `description`, `expression`, and `actions` attributes are required.
- The `enabled` and `position` attributes are optional.
- Refer to the Validation Overview section for more information on input validation

**important:** Newly created rules are enabled by default and added to the end of the ruleset unless specified otherwise. A maximum of 500 custom rules is allowed.

Use the [B2C CLI](https://developer.salesforce.com/docs/commerce/b2c-commerce/guides/b2c-developer-tooling.md):

```bash
# Required scopes: sfcc.cdn-zones, sfcc.cdn-zones.rw
export SFCC_CLIENT_ID='your-account-manager-client-id'
export SFCC_CLIENT_SECRET='your-account-manager-client-secret'
export SFCC_SHORTCODE='your-short-code'

npx @salesforce/b2c-cli ecdn firewall create \
  --tenant-id abcd_stg --zone stg-abcd-example-com.cc-ecdn.net \
  --description "Skip Merchant Approval" \
  --expression '(http.user_agent contains "MerchantApprovalServiceClient")' \
  --actions skip_custom_rules,skip_wafv2 --no-enabled \
  --before ffffe61cf25e4ec49c34b029ff3060f7
```

Alternatively, use the API:

```sh
curl "https://$CODE.api.commercecloud.salesforce.com/cdn/zones/v1/organizations/$ORG/zones/$ZONE/firewall-custom/rules" \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
--data '{
    "description": "Skip Merchant Approval",
    "expression": "(http.user_agent contains \"MerchantApprovalServiceClient\")",
    "actions": ["skip_custom_rules", "skip_wafv2"],
    "enabled": false,
    "position": {
        "before": "ffffe61cf25e4ec49c34b029ff3060f7"
    }
}'
```

### Sample Success Response - 201 HttpStatus Code

Response body contains the custom rule that was created.

```json
{
  "data": {
    "ruleId": "2c0fc9fa937b11eaa1b71c4d701ab86e",
    "description": "Skip Merchant Approval",
    "expression": "(http.user_agent contains \"MerchantApprovalServiceClient\")",
    "actions": ["skip_custom_rules", "skip_wafv2"],
    "lastUpdated": "2022-12-14T21:25:22.329194Z",
    "enabled": false
  }
}
```

## Get All Custom Rules

This endpoint returns all of the custom rules in the specified zone. If no custom rules exist, a 404 Not Found response is returned.

```sh
curl "https://$CODE.api.commercecloud.salesforce.com/cdn/zones/v1/organizations/$ORG/zones/$ZONE/firewall-custom/rules" \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json'
```

### Sample Success Response - 200 HttpStatus Code

Response body contains all of the existing custom rules in the specified zone.

```json
{
  "data": [
    {
      "ruleId": "2c0fc9fa937b11eaa1b71c4d701ab86e",
      "description": "Skip Merchant Approval",
      "expression": "(http.user_agent contains \"MerchantApprovalServiceClient\")",
      "actions": ["skip_custom_rules", "skip_wafv2"],
      "lastUpdated": "2022-12-14T21:25:22.329194Z",
      "enabled": true
    },
    {
      "ruleId": "ffffe61cf25e4ec49c34b029ff3060f7",
      "description": "Block Cuba",
      "expression": "(ip.src.country eq \"CU\")",
      "actions": ["block"],
      "lastUpdated": "2022-12-14T21:27:45.245836Z",
      "enabled": true
    }
  ]
}
```

## Get a Custom Rule

This endpoint returns the requested custom rule. If the requested rule does not exist, a 404 Not Found response is returned.

```sh
curl "https://$CODE.api.commercecloud.salesforce.com/cdn/zones/v1/organizations/$ORG/zones/$ZONE/firewall-custom/rules/$RULEID" \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json'
```

### Sample Success Response - 200 HttpStatus Code

Response body contains the requested custom rule.

```json
{
  "data": {
    "ruleId": "2c0fc9fa937b11eaa1b71c4d701ab86e",
    "description": "Skip Merchant Approval",
    "expression": "(http.user_agent contains \"MerchantApprovalServiceClient\")",
    "actions": ["skip_custom_rules", "skip_wafv2"],
    "lastUpdated": "2022-12-14T21:25:22.329194Z",
    "enabled": false
  }
}
```

## Update a Custom Rule

This endpoint updates the requested custom rule. If the requested rule does not exist, a 404 Not Found response is returned.

- The user must provide at least one of the following attributes in the request body: `description`, `expression`, `actions`, `enabled`, or `position`.

```sh
curl "https://$CODE.api.commercecloud.salesforce.com/cdn/zones/v1/organizations/$ORG/zones/$ZONE/firewall-custom/rules/$RULEID" \
--request 'PATCH' \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
--data '{
    "description": "Block Merchant Approval",
    "actions": ["block"],
    "enabled": false,
    "position": {
        "after": "ffffe61cf25e4ec49c34b029ff3060f7"
    }
}'
```

### Sample Success Response - 200 HttpStatus Code

Response body contains the requested rule.

```json
{
  "data": {
    "ruleId": "2c0fc9fa937b11eaa1b71c4d701ab86e",
    "description": "Block Merchant Approval",
    "expression": "(http.user_agent contains \"MerchantApprovalServiceClient\")",
    "actions": ["block"],
    "lastUpdated": "2022-12-14T21:27:22.329194Z",
    "enabled": false
  }
}
```

## Update the Order of All Custom Rules

This endpoint updates the order of all existing custom rules. The user provides an array of `ruleIds` that represents the new rule order. The array must contain exactly all of the existing custom rule ruleIds.

```sh
curl "https://$CODE.api.commercecloud.salesforce.com/cdn/zones/v1/organizations/$ORG/zones/$ZONE/firewall-custom/rules" \
--request 'PATCH' \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
--data '{
    "ruleIds": ["ffffe61cf25e4ec49c34b029ff3060f7", "2c0fc9fa937b11eaa1b71c4d701ab86e"]
}'
```

### Sample Success Response - 200 HttpStatus Code

Response body contains all of the existing custom rules in updated rule order.

```json
{
  "data": [
    {
      "ruleId": "ffffe61cf25e4ec49c34b029ff3060f7",
      "description": "Block Cuba",
      "expression": "(ip.src.country eq \"CU\")",
      "actions": ["block"],
      "lastUpdated": "2022-12-14T21:27:45.245836Z",
      "enabled": true
    },
    {
      "ruleId": "2c0fc9fa937b11eaa1b71c4d701ab86e",
      "description": "Skip Merchant Approval",
      "expression": "(http.user_agent contains \"MerchantApprovalServiceClient\")",
      "actions": ["skip_custom_rules", "skip_wafv2"],
      "lastUpdated": "2022-12-14T21:25:22.329194Z",
      "enabled": true
    }
  ]
}
```

## Delete a Custom Rule

This endpoint deletes the requested custom rule. If the requested rule does not exist, a 404 Not Found response is returned.

```sh
curl "https://$CODE.api.commercecloud.salesforce.com/cdn/zones/v1/organizations/$ORG/zones/$ZONE/firewall-custom/rules/$RULEID" \
--request 'DELETE' \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json'
```

### Sample Success Response - 204 HttpStatus Code (No Content)

## Custom Rules FAQ

- How do I construct the rule expression?
  - See the [Cloudflare documentation](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/) for more information regarding constructing rule expressions.
