Skip to main content

Profile Format Reference

This document describes the profile JSON format used by cfwrv1.sh and cfwrv2.sh to define WAF rules.

Profile Selectors​

Commands that take a profile (create-rules, update-rules, upgrade-default-rules, print-profile, validate-profile) resolve the selector in this order:

  1. Filename — profiles/<selector>.json
  2. Internal name — the first profile whose top-level name field matches <selector>

default is a symlink to the latest numbered release, so create-rules default always deploys the current stable rules while still tracking new releases. The Name column shown by list-profiles is always a valid selector.

To build a v3 profile without hand-writing expressions, use the rule generator: it exports the same shape, ready to save under profiles/.

Schema Versions​

VersionDescriptionStatus
v2Legacy format using priority field with allow/bypass actions for the deprecated Firewall Rules APIDeprecated
v3Rulesets API format with enabled, logging, and action_parameters fieldsCurrent

v3 Profile Format​

The v3 format maps directly to the Cloudflare Rulesets API. Rule ordering is determined by array position — rules are evaluated in order.

Top-Level Structure​

{
"name": "my-profile",
"description": "My WordPress WAF rules",
"version": 3,
"profiles_version": "3.0.0",
"phase": "http_request_firewall_custom",
"rules": [...]
}
FieldTypeRequiredDescription
namestringYesProfile name (used for identification)
descriptionstringYesHuman-readable description
versionnumberYesSchema version — must be 3
profiles_versionstringNoVersion of this profile file
phasestringNoRuleset phase (default: http_request_firewall_custom)
rulesarrayYesArray of rule objects

Rule Object​

{
"rule_number": "1",
"rule_version": "300",
"description": "R1V300 - Allow trusted IPs",
"expression": "(ip.src in { 192.0.2.1 192.0.2.2 })",
"action": "skip",
"enabled": true,
"logging": { "enabled": false },
"action_parameters": {
"ruleset": "current"
}
}
FieldTypeRequiredDescription
rule_numberstringYesInternal rule identifier for upgrade tracking
rule_versionstringYesInternal version for upgrade comparison
descriptionstringYesHuman-readable description
expressionstringYesCloudflare WAF expression
actionstringYesAction to take when rule matches
enabledbooleanNoWhether the rule is active (default: true)
loggingobjectNoLogging configuration (default: {"enabled": true})
action_parametersobjectNoAction-specific parameters

Supported Actions​

ActionDescriptionv2 Equivalent
blockBlock the requestblock
challengeIssue a CAPTCHA challengechallenge
js_challengeIssue a JavaScript challengejs_challenge
managed_challengeIssue a managed challenge (CAPTCHA or JS based on risk)managed_challenge
logLog the request without taking actionlog
skipSkip remaining rules and/or security productsallow + bypass
executeExecute another ruleset—

Skip Action Configuration​

The skip action replaces the deprecated allow and bypass actions.

Skip remaining custom rules:

"action_parameters": {
"ruleset": "current"
}

Skip specific security products:

"action_parameters": {
"phases": ["http_request_firewall_managed", "http_ratelimit"]
}

Both:

"action_parameters": {
"ruleset": "current",
"phases": ["http_request_firewall_managed"]
}

Custom Block Response​

The block action supports a custom response configuration:

"action_parameters": {
"response": {
"status_code": 403,
"content": "Your request was blocked.",
"content_type": "text/plain"
}
}

Supported content_type values: text/html, text/plain, application/json, application/xml, text/xml.

Rate Limiting Configuration​

Rate limiting can be applied to any action:

"action_parameters": {
"ratelimit": {
"characteristics": ["ip.src"],
"period": 60,
"requests_per_period": 100,
"mitigation_timeout": 300
}
}

Converting v2 to v3​

There is no conversion script; the change is small enough to do by hand, and every profile in profiles/ is already v3. Key conversions:

  • priority → removed (order is array position)
  • allow → skip with "action_parameters": { "ruleset": "current" }
  • bypass → skip with "action_parameters": { "phases": [...] }
  • enabled: true is added to each rule
  • logging is added (disabled for skip rules to reduce noise)

Validation​

Validate a profile against the Rulesets API schema:

./cfwr.sh -c validate-profile <profile-name>