The Core Rule Set, run by Coraza, on each request's method, URL and headers (closes #25)
check / check (push) Waiting to run

Coraza v3.8.1 runs the Core Rule Set 4.25.0 (coraza-coreruleset v4.25.0)
after the rule files, with the six changes and the default
SWWAF_WAF_DISABLED_RULES that SPEC.md gives; no body, no response. The
parameter names in the third and fourth changes are matched in any case,
as Coraza does. SWWAF_WAF_DISABLED_RULES refuses 900000 to 900999,
smallwebwaf's own rules. A request with more than 1000 query parameters
adds 5 (rule 900300). In block mode a match is refused with 403, an
offence counted toward the error burst; in detect mode it is let
through. Both log waf_rule_ids, waf_score and duration_waf, raise
waf_block, and count smallwebwaf_waf_matches_total.

Judgement call: waf_block is raised in block mode too.
Deviation: no engine-error path; with no body read, Coraza cannot fail.

Model: opus-5-5
This commit was merged in pull request #121.
This commit is contained in:
2026-10-08 09:37:13 +02:00
parent e81a7f0ca2
commit 80f4c2cc61
21 changed files with 1721 additions and 233 deletions
+8 -8
View File
@@ -84,12 +84,12 @@ func (rq *request) countBytes() {
}
// countRefusal counts the request for the error burst once it has been
// answered, if smallwebwaf refused it after a rule file match or a trap
// path, or for a missing or wrong token, and in observe mode if enforce
// mode would have: more than SWWAF_ERROR_BURST_THRESHOLD such refusals of
// the client within a minute break a limit. A client in SWWAF_ALLOW_NETS,
// which the checks skip, is not counted, and nothing is while the
// threshold is off.
// answered, if smallwebwaf refused it after a rule file match, a trap path
// or a Core Rule Set match, or for a missing or wrong token, and in
// observe mode if enforce mode would have: more than
// SWWAF_ERROR_BURST_THRESHOLD such refusals of the client within a minute
// break a limit. A client in SWWAF_ALLOW_NETS, which the checks skip, is
// not counted, and nothing is while the threshold is off.
func (rq *request) countRefusal() {
cfg := rq.h.config
if cfg.ErrorBurstThreshold == 0 {
@@ -100,7 +100,7 @@ func (rq *request) countRefusal() {
// before it reached the endpoint has had no token refused there.
tokenRefused := rq.tokenRefused && rq.line.WouldAction == "" &&
!isInside(rq.client, cfg.AllowNets)
if !rq.attack && !rq.ruleBlocked && !tokenRefused {
if !rq.attack && !rq.ruleBlocked && !rq.wafBlocked && !tokenRefused {
return
}
@@ -116,7 +116,7 @@ func (rq *request) countRefusal() {
status := rq.out.status
switch rq.line.WouldAction {
case requestlog.ActionRuleBlocked:
case requestlog.ActionRuleBlocked, requestlog.ActionWAFBlocked:
status = http.StatusForbidden
case requestlog.ActionBanned:
status = cfg.BanResponse