Stop a WAF score below GREY_MIN escalating under the grey gate #3

Merged
james merged 1 commit from grey-min-floor into main 2026-10-07 18:33:17 +00:00
Owner

Problem

Under CENTINELA_GATE=grey, CENTINELA_GREY_MIN only ever gated out score-0 requests. The pre-filter flagged any request with a positive WAF score, and the grey gate falls through to the pre-filter, so a score of 1 or more always reached the model.

Seen on v0.1.3 with the embedded WAF at paranoia 3 and GREY_MIN=4: 25 of 26 recent decisions for one host had waf_score 3 (CRS 942420 on ordinary session cookies) and were all escalated, then failed open as "model unavailable" once the backend queued past the budget.

Change

  • Suspicious() looks only at the request itself (method, path, query, headers, body). It no longer treats a WAF score as a marker.
  • escalate() weighs the score per gate:
    • grey: at or above GreyMin, or anything the pre-filter flags. A score below the floor with no marker passes without a model call.
    • suspicious: unchanged, any positive score still escalates.
    • always: unchanged.
  • README gate descriptions updated to match.

The eval harness already computed score >= grey-min || suspicious; with the pre-filter no longer counting the score, it now matches the engine for --grey-min above 1. Results at the default of 1 are unchanged.

Tests

  • TestGreyGateMin (GreyMin=4): score 3 with no markers is not escalated; score 3 with a marker is; scores 4 and 7 are.
  • TestSuspiciousGateWAFScore: the suspicious gate still escalates a positive score and passes score 0.
  • TestSuspicious: a WAF score alone is no longer flagged by the pre-filter.

make vet and make test pass.

Release note

Merging to main runs build-and-push, which tags and publishes the next patch version.

## Problem Under `CENTINELA_GATE=grey`, `CENTINELA_GREY_MIN` only ever gated out score-0 requests. The pre-filter flagged any request with a positive WAF score, and the grey gate falls through to the pre-filter, so a score of 1 or more always reached the model. Seen on v0.1.3 with the embedded WAF at paranoia 3 and `GREY_MIN=4`: 25 of 26 recent decisions for one host had `waf_score` 3 (CRS 942420 on ordinary session cookies) and were all escalated, then failed open as "model unavailable" once the backend queued past the budget. ## Change - `Suspicious()` looks only at the request itself (method, path, query, headers, body). It no longer treats a WAF score as a marker. - `escalate()` weighs the score per gate: - `grey`: at or above `GreyMin`, or anything the pre-filter flags. A score below the floor with no marker passes without a model call. - `suspicious`: unchanged, any positive score still escalates. - `always`: unchanged. - README gate descriptions updated to match. The eval harness already computed `score >= grey-min || suspicious`; with the pre-filter no longer counting the score, it now matches the engine for `--grey-min` above 1. Results at the default of 1 are unchanged. ## Tests - `TestGreyGateMin` (`GreyMin=4`): score 3 with no markers is not escalated; score 3 with a marker is; scores 4 and 7 are. - `TestSuspiciousGateWAFScore`: the suspicious gate still escalates a positive score and passes score 0. - `TestSuspicious`: a WAF score alone is no longer flagged by the pre-filter. `make vet` and `make test` pass. ## Release note Merging to `main` runs `build-and-push`, which tags and publishes the next patch version.
Stop a WAF score below GREY_MIN escalating under the grey gate
All checks were successful
security-scan / security-scan (pull_request) Successful in 1m16s
test / go (pull_request) Successful in 4m27s
6465bddbcc
The pre-filter flagged any request with a positive WAF score, and the
grey gate falls through to the pre-filter, so CENTINELA_GREY_MIN only
ever gated out score-0 requests. With GREY_MIN=4 at paranoia 3, CRS
942420 firing on ordinary session cookies (score 3) sent nearly every
logged-in request to the model.

Suspicious() now looks only at the request text. The engine weighs the
score per gate: grey escalates at or above GreyMin, suspicious keeps
escalating any positive score. The pre-filter's markers still escalate
under grey, so score-0 recon is covered as before.

The eval harness already computed "score >= grey-min || suspicious"; it
now matches the engine for grey-min above 1 as well. Results at the
default grey-min of 1 are unchanged.

🔎 ojo scan results

Severity Count
🟠 HIGH 1
🟢 LOW 1
Details (2)
Type Severity ID/Rule Location Description
vuln 🟠 HIGH CVE-2026-41510 github.com/corazawaf/coraza/[email protected] Coraza: Silent argument drop at ArgumentLimit allows bypass of ARGS-targeted rules via parameter flooding
misconfig 🟢 LOW dockerfile-no-healthcheck Dockerfile:1 image has no HEALTHCHECK
<!-- ojo-scan-summary --> ### 🔎 ojo scan results | Severity | Count | |---|---| | 🟠 HIGH | 1 | | 🟢 LOW | 1 | <details><summary>Details (2)</summary> | Type | Severity | ID/Rule | Location | Description | |---|---|---|---|---| | vuln | 🟠 HIGH | <a href="https://github.com/corazawaf/coraza/security/advisories/GHSA-6r3q-mjv7-xr8m" target="_blank" rel="noopener noreferrer">CVE-2026-41510</a> | github.com/corazawaf/coraza/[email protected] | Coraza: Silent argument drop at ArgumentLimit allows bypass of ARGS-targeted rules via parameter flooding | | misconfig | 🟢 LOW | dockerfile-no-healthcheck | <a href="https://git.colibrisec.org/ColibriSec/centinela/src/commit/6465bddbcc62a16185a673b462d4675c858745bb/Dockerfile#L1" target="_blank" rel="noopener noreferrer">Dockerfile:1</a> | image has no HEALTHCHECK | </details>
james merged commit 476456de08 into main 2026-10-07 18:33:17 +00:00
james deleted branch grey-min-floor 2026-10-07 18:33:18 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
ColibriSec/centinela!3
No description provided.