ADR-0017: The default phase is 2 and is never inherited
ADR-0017: The default phase is 2 and is never inherited
- Status: proposed
- Date: 2026-10-06
- Deciders: @fzipi
- Category: Divergence
Context
A rule may omit the phase action. What phase it then runs in:
- ModSecurity v2 (
apache2/re.c,actionset->phase = 2whenNOT_SET): phase 2, but a phase-less rule first inherits the phase of the currentSecDefaultAction(msre_actionset_merge,if (child->phase != NOT_SET) merged->phase = child->phase), because v2 keeps one current default action set rather than one per phase. - libmodsecurity v3 (
headers/modsecurity/rule.h,m_phase(RequestHeadersPhase)): phase 1. - Coraza 3.8.1 (
internal/corazawaf/rule.go,Phase_: 2): phase 2; default actions are looked up by the rule’s own phase (rule_parser.go).
The ModSecurity reference manual documents phase 2 as the default. OWASP CRS sets phase
on every rule, so the question only arises in hand-written rules.
Decision
A rule without a phase action runs in phase 2. The phase is never taken from a
SecDefaultAction. Normative text: spec/03-processing-model.md#phases.
Options considered
- Phase 1 (v3): contradicts the manual and the other two engines; rejected.
- Phase 2 with v2-style inheritance: makes the meaning of a rule depend on which
SecDefaultActionprecedes it; rejected. - Phase 2, no inheritance (chosen): manual, Coraza, and v2 whenever no
SecDefaultActionis in effect.
Consequences
- For libmodsecurity v3: change the default to
RequestBodyPhase(default-phase.yamlfails on v3 today). - For ModSecurity v2: stop inheriting
phasefrom the default action set. - For rule authors: always write
phase:; the tests in this repository do.