## WAF settings (`waf-settings`)

Platform-wide WAF master switch, default blocking threshold and request body inspection limit; admin only. Per-site observe/block mode and exceptions live in the site config field waf.

Authentication: Admin only · Docs: https://www-demo.kuxitong.com/en/docs/api/waf-settings

### GET `/api/v2/waf-settings`

Get WAF settings · Authentication: Admin only

```sh
curl "https://panel.example.com/api/v2/waf-settings" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### PUT `/api/v2/waf-settings`

Update WAF settings · Authentication: Admin only

Request body:

| Field | Type | Required | Description |
|---|---|---|---|
| `body_max_kb` | integer | Yes | Only the first this many KiB of the request body are inspected; 0 = body not inspected. |
| `enabled` | boolean | Yes | Platform-wide master switch; false = no site is inspected. |
| `engine_unavailable_nodes` | integer |  | Number of online primary nodes reporting the WAF engine (libinjection) unavailable (the sqli/xss rules do not take effect there); ignored on update. |
| `enhanced` | string |  | WAF enhanced state - full (active), readonly (expired but within the read-only buffer, License.readonly_days, 7 days by default; standard/strict level and semantic detection still work but are read-only) or basic (not purchased or past the buffer; not in effect, settings kept); ignored on update. Values: ["full","readonly","basic"] |
| `expected_updated_at` | string |  | Optimistic lock - the updated_at as the caller read it (the version of the node.global config key, shared by CC and WAF settings; use 1970-01-01T00:00:00Z when the read value is null). If it differs from the stored one, 409 stale_version is returned and nothing is saved; omit to skip the check. |
| `intel_share` | boolean |  | Threat intelligence sharing - anonymously report auto-banned risky IPs, upload-scan hits/false positives and new file fingerprints to the provider (records via GET /intel-reports). Omit to keep the stored value; on when never set (on by default; can be turned off anytime, reporting stops immediately). |
| `level` | string |  | Platform default protection level (used by sites that did not pick one); standard/strict are WAF enhanced and go through the enhanced gate (while read-only or not purchased the level can only be lowered, not raised). Omit to keep the stored value; basic when never set. Values: ["basic","standard","strict"] |
| `observe_days` | integer |  | Observation days for new rules/levels (log only, no blocking); 0 = no observation. Omit to keep the stored value; 3 when never set. |
| `rule_lib` | WafRuleLib |  | Rule library overview (read-only, ignored on update) - whether the paid feature rules_update is on, package version, counts per class and node alignment; without it nodes use the 23 built-in rules. Details via GET /waf-protections. |
| `scanner` | WafScanner |  | Scanner protection (scan section of the built-in guard) - master switch, action and ban duration, plus the five judging rules (any one triggers) each with its own switch and thresholds/custom lists. A rule that is switched off is not judged; custom paths live on the master and survive rule-pack updates. |
| `semantic` | WafSemantic |  | Semantic detection (WAF enhanced) - judges attacks by meaning on top of rule scoring; the node enforces it. |
| `threshold` | integer | Yes | Default blocking threshold (sum of anomaly scores of matched rules); a non-zero site waf.threshold takes precedence. |
| `trunc_action` | string |  | Action when part of a request was not inspected (rule 920901) - more than 1024 parameters, more than 256 headers, JSON/XML items over the limit, form fields over the budget, or a non-binary body larger than body_max_kb. Whatever can be re-checked is re-checked first; only what is still uncovered is handled by this setting. log only records (event tagged body_trunc) and never blocks; strict_block blocks at the strict level and only records at basic/standard; block blocks at every level. Default strict_block: at the strict level a non-binary body above body_max_kb (64 KB by default, e.g. a large JSON) is blocked by 920901 - raise body_max_kb, set log, or exempt 920901 in the site WAF exceptions. Note 920901 counts toward the repeated-hit ban (site waf.ban_on_repeat); on sites where it is enabled, client IPs that routinely send large JSON get banned. Sites in observe mode only record. Omit to keep the stored value; strict_block when never set. Values: ["log","strict_block","block"] |
| `updated_at` | string |  | Version in the response (updated_at of the node.global config key; null if never changed); ignored on update - use expected_updated_at for the optimistic lock. |

```sh
curl -X PUT "https://panel.example.com/api/v2/waf-settings" \
  -H "X-API-Key: $GOCDN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"body_max_kb":64,"enabled":true,"intel_share":true,"level":"basic","observe_days":3,"scanner":{"action":"ban","ban_s":1800,"by_app_enabled":true,"decoys":{"enabled":true,"paths":[]},"enabled":true,"not_found":{"enabled":true,"max":30,"window_s":60},"sensitive":{"enabled":true,"extra_paths":[],"max":3},"ua_enabled":true},"semantic":{"enabled":false,"items":["sqli","xss"],"observe_days":3,"relation":"rules_first","sensitivity":"mid"},"threshold":5,"trunc_action":"strict_block"}'
```

WAF settings object:

| Field | Type | Required | Description |
|---|---|---|---|
| `body_max_kb` | integer |  | Only the first this many KiB of the request body are inspected; 0 = body not inspected. |
| `enabled` | boolean |  | Platform-wide master switch; false = no site is inspected. |
| `engine_unavailable_nodes` | integer |  | Number of online primary nodes reporting the WAF engine (libinjection) unavailable (the sqli/xss rules do not take effect there); ignored on update. (read-only) |
| `enhanced` | string |  | WAF enhanced state - full (active), readonly (expired but within the read-only buffer, License.readonly_days, 7 days by default; standard/strict level and semantic detection still work but are read-only) or basic (not purchased or past the buffer; not in effect, settings kept); ignored on update. Values: ["full","readonly","basic"] (read-only) |
| `expected_updated_at` | string |  | Optimistic lock - the updated_at as the caller read it (the version of the node.global config key, shared by CC and WAF settings; use 1970-01-01T00:00:00Z when the read value is null). If it differs from the stored one, 409 stale_version is returned and nothing is saved; omit to skip the check. |
| `intel_share` | boolean |  | Threat intelligence sharing - anonymously report auto-banned risky IPs, upload-scan hits/false positives and new file fingerprints to the provider (records via GET /intel-reports). Omit to keep the stored value; on when never set (on by default; can be turned off anytime, reporting stops immediately). |
| `level` | string |  | Platform default protection level (used by sites that did not pick one); standard/strict are WAF enhanced and go through the enhanced gate (while read-only or not purchased the level can only be lowered, not raised). Omit to keep the stored value; basic when never set. Values: ["basic","standard","strict"] |
| `observe_days` | integer |  | Observation days for new rules/levels (log only, no blocking); 0 = no observation. Omit to keep the stored value; 3 when never set. |
| `rule_lib` | WafRuleLib |  | Rule library overview (read-only, ignored on update) - whether the paid feature rules_update is on, package version, counts per class and node alignment; without it nodes use the 23 built-in rules. Details via GET /waf-protections. (read-only) |
| `scanner` | WafScanner |  | Scanner protection (scan section of the built-in guard) - master switch, action and ban duration, plus the five judging rules (any one triggers) each with its own switch and thresholds/custom lists. A rule that is switched off is not judged; custom paths live on the master and survive rule-pack updates. |
| `semantic` | WafSemantic |  | Semantic detection (WAF enhanced) - judges attacks by meaning on top of rule scoring; the node enforces it. |
| `threshold` | integer |  | Default blocking threshold (sum of anomaly scores of matched rules); a non-zero site waf.threshold takes precedence. |
| `trunc_action` | string |  | Action when part of a request was not inspected (rule 920901) - more than 1024 parameters, more than 256 headers, JSON/XML items over the limit, form fields over the budget, or a non-binary body larger than body_max_kb. Whatever can be re-checked is re-checked first; only what is still uncovered is handled by this setting. log only records (event tagged body_trunc) and never blocks; strict_block blocks at the strict level and only records at basic/standard; block blocks at every level. Default strict_block: at the strict level a non-binary body above body_max_kb (64 KB by default, e.g. a large JSON) is blocked by 920901 - raise body_max_kb, set log, or exempt 920901 in the site WAF exceptions. Note 920901 counts toward the repeated-hit ban (site waf.ban_on_repeat); on sites where it is enabled, client IPs that routinely send large JSON get banned. Sites in observe mode only record. Omit to keep the stored value; strict_block when never set. Values: ["log","strict_block","block"] |
| `updated_at` | string |  | Version in the response (updated_at of the node.global config key; null if never changed); ignored on update - use expected_updated_at for the optimistic lock. (read-only) |
