SYSTEM Cited by 1 source
Cloudflare rulesets engine¶
Cloudflare's rulesets engine is the edge component that
evaluates sets of (filter, action) rules against each request
entering Cloudflare's network. It backs the customer-facing
WAF Managed Rulesets + bot-management +
other rule-driven edge policy.
The engine runs in both proxy generations — FL1 has a Lua implementation; FL2 has a Rust rewrite.
Concepts¶
- Rule. A
(filter, action)pair. The filter selects traffic (URL path, header, method, etc.); the action applies an effect. - Ruleset. An ordered set of rules evaluated together.
- Action.
block,log,skipare typical actions. A distinguished action —execute— triggers evaluation of another (sub-)ruleset.
The execute action¶
The execute action is how top-level rulesets compose with
sub-rulesets. Cloudflare's internal logging system uses this
mechanism to evaluate new test rules before they're rolled out
to public customers: a top-level ruleset's execute points at
a sub-ruleset containing the test rules. The test rules'
evaluation results are attached to the top-level result via
rule_result.execute.results.
The killswitch subsystem¶
The rulesets engine ships a killswitch that can rapidly disable a misbehaving rule. The killswitch receives its input from Cloudflare's global configuration system (seconds-to-fleet propagation, no staged rollout). A well-defined SOP exists for its use; it has been used many times in the past without incident.
The 2025-12-05 bug¶
On 2025-12-05, the killswitch was applied to a rule with
action=execute for the first time in production — to
disable the internal WAF test-rules sub-ruleset when it couldn't
support a larger WAF body buffer. The Lua evaluation code
correctly skipped the execute action (did not evaluate the
sub-ruleset); but the post-processing step then ran:
if rule_result.action == "execute" then
rule_result.execute.results = ruleset_results[tonumber(rule_result.execute.results_index)]
end
Because the rule had been skipped, the rule_result.execute
object — which usually holds the execute-action metadata — did
not exist. Lua threw:
[lua] Failed to run module rulesets callback late_routing:
/usr/local/nginx-fl/lua/modules/init.lua:314:
attempt to index field 'execute' (a nil value)
HTTP 500 for every affected request for ~25 minutes. See the canonical concepts/nil-index-lua-bug wiki entry.
The Rust FL2 re-implementation did not have this bug — "This type of code error is prevented by languages with strong type systems." Canonical wiki instance of patterns/rust-replacement-of-dynamic-language-hot-path.
Pipeline position¶
On a zone with the Cloudflare Managed Ruleset deployed, each request flows through:
- WAF pre-processing + body buffering (128 KB, raised to 1 MB during the 12-05 rollout).
- Rulesets engine — evaluate the top-level ruleset;
executeactions may fan out to sub-rulesets (internal test rules, DDoS Managed Rulesets, etc.). - Post-processing of rule results.
- Subsequent edge handlers (bot management, [[systems/pay-per- crawl|pay-per-crawl]] if enabled, …).
The engine therefore sits on the hot path of every request, which is why a single dereference on a rarely-taken branch produced a fleet-wide outage.
Seen in¶
- sources/2025-12-05-cloudflare-outage-on-december-5-2025 —
canonical wiki instance: the engine's killswitch path on an
execute-action rule, never before exercised in production, hit a seven-year-old nil-index bug in the Lua FL1 impl; Rust FL2 was unaffected.