Name log fields, metrics and the Core Rule Set package for what they are (closes #192)
check / check (push) Failing after 3m22s

The first half of the naming audit: names now say what they are. `internal/waf` is `internal/coreruleset`. Log fields, the action `blocked_by_core_rule_set`, the metric and the alert event say Core Rule Set. Timings end `_ms`. Percentages say of what, as `rate_limit_percent` and `bytes_limit_percent`. Setting names follow in #234.

Judgement call: `blocked_by_core_rule_set`, not the audit's `core_rule_set_blocked`, to match `blocked_by_block_rule`.
Trips a reader: an existing state file holding `waf_blocked` or the anomaly scope `watch` stops the start and must be removed. `SWW_ALERT_EVENTS` listing `waf_block` must list `core_rule_set_match`.

Model: opus-5-5
This commit was merged in pull request #242.
This commit is contained in:
clawbot committed 2026-11-09 08:47:26 +01:00
1 parent aede434f6a
commit 719691d1e8
58 files changed
+743 -691

No files matched your search

+13 -13
View File
@@ -9,8 +9,8 @@ import (
"sneak.berlin/go/smallwebwaf/internal/alerts"
"sneak.berlin/go/smallwebwaf/internal/config"
"sneak.berlin/go/smallwebwaf/internal/coreruleset"
"sneak.berlin/go/smallwebwaf/internal/requestlog"
"sneak.berlin/go/smallwebwaf/internal/waf"
)
// coreRuleSet inspects the request with the Core Rule Set, unless
@@ -18,7 +18,7 @@ import (
// pathExempt decides, and notes the rules it matched and its score in the
// log line, and the rules in the metrics. A score at or over
// SWW_WAF_ANOMALY_THRESHOLD is a match: it adds the tag exploitsignature,
// raises the waf_block alert, and in block mode refuses the request with 403,
// raises the core_rule_set_match alert, and in block mode refuses the request with 403,
// which is an offence its client's history counts. Its figures are the score
// and the threshold.
type coreRuleSet struct{}
@@ -38,12 +38,12 @@ func (coreRuleSet) check(_ context.Context, rq *request, _ time.Time) *verdict {
result, read, _ := rq.h.coreRuleSet.Inspect(rq.in, rq.client, rq.in.Body)
rq.requestBytes = int64(len(read))
rq.line.DurationWAF = new(requestlog.Milliseconds(time.Since(start)))
rq.line.WAFRuleIDs = result.RuleIDs
rq.line.WAFScore = &result.Score
rq.line.DurationCoreRuleSetMS = new(requestlog.Milliseconds(time.Since(start)))
rq.line.CoreRuleSetRuleIDs = result.RuleIDs
rq.line.CoreRuleSetScore = &result.Score
for _, id := range result.RuleIDs {
rq.h.metrics.WAFMatched(cfg.WAFMode, id)
rq.h.metrics.CoreRuleSetMatched(cfg.WAFMode, id)
}
threshold := cfg.WAFAnomalyThreshold
@@ -52,26 +52,26 @@ func (coreRuleSet) check(_ context.Context, rq *request, _ time.Time) *verdict {
}
rq.addTag(config.ExploitSignatureTag)
rq.alertWAFBlock(result)
rq.alertCoreRuleSetMatch(result)
if cfg.WAFMode == config.WAFModeDetect {
return nil
}
rq.wafBlocked = true
rq.blockedByCoreRuleSet = true
return &verdict{
action: requestlog.ActionWAFBlocked,
action: requestlog.ActionBlockedByCoreRuleSet,
figures: map[string]any{figureScore: result.Score, "threshold": threshold},
}
}
// alertWAFBlock raises the waf_block alert for the request, which the Core
// Rule Set scored at result, at or over SWW_WAF_ANOMALY_THRESHOLD. Its
// alertCoreRuleSetMatch raises the core_rule_set_match alert for the request,
// which the Core Rule Set scored at result, at or over SWW_WAF_ANOMALY_THRESHOLD. Its
// detail gives the rule ids, the score, the method and the path with the
// query, and, for a request that is not refused for it, the mode: detect,
// or observe in observe mode.
func (rq *request) alertWAFBlock(result waf.Result) {
func (rq *request) alertCoreRuleSetMatch(result coreruleset.Result) {
detail := map[string]any{
"rule_ids": result.RuleIDs,
"score": result.Score,
@@ -87,7 +87,7 @@ func (rq *request) alertWAFBlock(result waf.Result) {
}
rq.h.alerts.Raise(alerts.Alert{
Event: alerts.EventWAFBlock,
Event: alerts.EventCoreRuleSetMatch,
Host: rq.site,
Client: rq.client,
Netblock: rq.h.clientGroup(rq.client),