Objective
Compile the complete ordered rule-configuration layer used by the stable ModSecurity 3.0.16 / Coraza 3.7.0 union: phase defaults, markers, local includes, authenticated remote rule sources, rule removals, action/target updates, duplicate policy, and explicit compatibility handling for missing update targets. All mutation occurs while building a candidate immutable plan; published plans and the request path remain read-only.
Behavioral contract
Ordered source assembly
- Preserve one deterministic logical directive stream across builder strings, files,
Include,IncludeOptional, and remote sources. - Local includes retain the WAF-10 canonical-root, cycle, depth, count, size, optional-glob, and source-provenance guarantees.
- Candidate failure cannot alter the active
Waf; publication is atomic after parsing, remote resolution, update application, and validation.
SecDefaultAction
- Store at most one immutable default snapshot per phase and attach rules only to the snapshot for their effective phase.
- Require an explicit valid phase and a non-
blockdisruptive action. - Reject duplicate phase defaults with a related span to the first declaration.
- Reject metadata/flow actions and
t:none; preserve ModSecurity-compatible ordered transformation inheritance for othert:actions. - Rules without
phaseremain phase 2; a default for another phase never changes their phase. - Explicit per-rule actions override singleton defaults while repeatable actions retain specified ordering.
Markers
- Compile
SecMarkerinto ordered, addressable plan nodes forskipAfterby text or numeric spelling. - Preserve duplicate names in source order and resolve to the next reachable marker after the executing rule.
- Diagnose unresolved static markers during compilation; dynamic macro-bearing references use bounded runtime lookup.
- Markers execute no operator or action and appear in phase control flow without becoming inspectable rules.
Rule selection and removal
SecRuleRemoveByIdaccepts bounded unsigned IDs and inclusive ranges.SecRuleRemoveByTagandSecRuleRemoveByMsguse bounded zig-regex selectors, retaining required ModSecurity regex behavior while documenting Coraza equality-only differences.- Removing a chain head removes the chain; selecting a non-head member is diagnosed rather than creating a partial chain.
- Removed rules leave phase/prefilter runtime indexes while source evidence retains the reason and directive span.
Target updates
SecRuleUpdateTargetById,ByTag, andByMsgcompile selectors once and apply additions/removals in directive order.- ID selectors support bounded lists and inclusive ranges.
- Target parsing preserves collection, key, regex-key, count, and negation semantics.
- Additions append in order; removals exclude matching prior targets without mutating unrelated targets.
- Updates apply atomically to every selected chain under documented upstream-compatible ownership rules.
Action updates
SecRuleUpdateActionByIdsupports bounded ID lists/ranges and parses its action list once.idandphasechanges are rejected.- Singleton actions replace the prior effective action of their family; repeatable actions append in source order.
- A disruptive update replaces the prior disruptive action; non-disruptive-only updates preserve it.
- Transformation updates honor ordered
t:nonereset semantics and rebuild precomputed pipelines/macros.
Missing targets, duplicates, and compatibility
- Strict mode is default: duplicate external rule IDs, malformed selectors, missing explicitly named IDs, partial-chain mutations, and invalid updates fail with stable diagnostics and primary/related spans.
- An explicit builder compatibility option may ignore only upstream-compatible rule-not-found update/removal cases and emits bounded structured warnings.
- Compatibility mode never suppresses malformed syntax, unsafe remote policy, duplicate IDs, allocation/resource failures, or invariant violations.
- No directive is silently accepted without an effect.
Authenticated remote rules
SecRemoteRules KEY HTTPS_URLresolves only during candidate construction through an injected async-capable fetch interface; transactions perform no network I/O.- URLs remain credential-free HTTPS and pass explicit host/IP/redirect policy, DNS-rebinding protection, timeout, byte, directive, and redirect limits.
- The key is sent only in the designated authentication header and is redacted from diagnostics, logs, fingerprints, and telemetry.
- Results record final URL, content digest, retrieval metadata, and provenance; identical pinned content may use a bounded cache.
Abortfails the candidate.Warnrecords a structured warning and continues without substituting stale or empty content unless an explicit pinned-cache policy allows it.- The transport interface is ready for WAF-42 zig-tls integration; tests use deterministic in-memory transports.
Public and plan interfaces
- Immutable typed rule-selection/update IR with stable source spans and bounded counts/bytes.
- Plan views for effective rules, removal evidence, marker resolution, and configuration warnings.
- Builder limits for selectors, intervals, updates, expansion, markers, remote responses, redirects, and warnings.
- Explicit strict/compatible missing-rule policy and remote host/redirect/cache decisions.
- Stable diagnostics must not renumber WAF-PLAN-0101 through WAF-PLAN-0108.
Deliverables
- Phase-scoped default validation and snapshots.
- Marker execution-plan integration and static resolution.
- ID interval parsing/indexing and removal application.
- Tag/message zig-regex selectors and removals.
- Target update compiler/application for ID/tag/message selectors.
- Action update compiler/application with singleton/repeatable semantics.
- Explicit missing-rule compatibility mode and structured warnings.
- Authenticated bounded HTTPS remote-source loader and explicit no-stale cache policy.
- Immutable effective-plan/evidence APIs and fingerprint coverage.
- Focused allocation-failure, hostile-input, differential, fuzz, corpus, and benchmark tests.
- Documentation and machine-readable compatibility evidence.
Acceptance criteria
- Every scoped directive has positive, negative, ordering, allocation-failure, and resource-limit coverage.
- Differential fixtures cover pinned ModSecurity and Coraza behavior; intentional union choices are named and executable.
- CRS 4.28 setup/exclusion streams compile with no unexplained skips.
- Candidate failures leave the active generation unchanged and caller-owned inputs valid.
- Published plans require no update parsing, regex compilation, remote/filesystem/database access, or allocation on the request path.
- Benchmarks record compile cost, plan size, and reload pause for CRS with and without exclusion/update overlays.
- Focused tests, full
zig build test,zig build check, corpus gates, formatting, and hosted CI pass on the exact closing SHA. - Work lands directly on
mainin small conventional commits with issue/commit/run links.
Relationships
- Parent: WAF-00 #1
- Unblocked by: WAF-12 #13
- Blocks: WAF-63 #64, WAF-64 #65
- Remote transport integration: WAF-42 #43
- Regex selectors: REGEX-02, REGEX-03
Baselines and upstream references
- ModSecurity 3.0.16:
seclang-parser.yy,rules_exceptions.cc, default-action and config-update regressions. - Coraza 3.7.0:
internal/seclang/directives.go,rule_parser.go, directive engine tests. - OWASP CRS 4.28.0: setup and rule-exclusion corpus.
- Zig 0.17-dev locked through Pantry; no Git submodules.