Surviving the Grey Zone: Why We Built Centinela, a Model-Driven IPS That Adjudicates Your WAF

Centinela Model-Driven Intrusion Prevention System Architecture
🛡️
Architecture Deep Dive: Model-Driven Intrusion Prevention An inside look at Centinela (centinela-2f) and Laya, our self-hosted, fine-tuned multilingual decision engine that arbitrates WAF grey zones, slashes false positives by up to 80%, and makes OWASP CRS Paranoia Level 3 usable in production.

Anyone who has ever operated an enterprise Web Application Firewall (WAF) in production knows the sacred, unspoken rule of the OWASP Core Rule Set (CRS):

"You shall run Paranoia Level 1 without fear, test Paranoia Level 2 on staging, and never, under any circumstances, turn on Paranoia Level 3 in production unless your goal is an impromptu self-inflicted denial of service."

The dirty secret of signature-based web security isn't that regex engines can't spot attacks. It’s that they can't tell the difference between an escalating SQL injection attack and an Irish user named O'Reilly creating an account. They can't distinguish an active directory traversal payload from an awkward relative path in a legitimate webhook, and they treat a developer pasting a code snippet into a bug tracker like an active nation-state intrusion.

When we ran our grey-zone benchmark probe set against OWASP CRS at Paranoia Level 3 (PL3), it achieved an admirable 82.8% attack detection rate. The catch? It also blocked 51.3% of totally benign requests. Flip that switch in production, and half your customers are staring at 403 Forbidden screens while your on-call engineer reconsiders their career choices.

So we built Centinela.

Centinela is an inline, model-driven Intrusion Prevention System (IPS) written in Go. But rather than foolishly replacing the WAF with an expensive, hallucination-prone cloud LLM, Centinela does something much more sensible: it adjudicates the WAF's grey zone using a fast, purpose-built decision engine named Laya.


1. The Core Philosophy: The WAF is a Detective, Not a Judge

Traditional security discussions treat WAFs and AI models like rival sports teams. Traditionalists insist regexes are fast and deterministic. AI hype merchants insist generative models should inspect every single TCP packet passing through your edge. Both extremes miss the mark.

Regexes are blazingly fast (μs) but context-blind. Heavy general-purpose LLMs possess deep semantic nuance but are computationally expensive (ms) and can be tricked by clever rhetoric.

Centinela marries the two by treating OWASP CRS as an investigative detective, and our decision engine (Laya) as the courtroom judge:

client -> proxy -> WAF (CRS PL3) -> centinela -> app
                     |                  |
              anomaly score     shunned? bypass? hard-block? cache? gate?  (μs, no model)
                                        |
                         grey zone (flagged, not certain) -> Laya -> policy
                                        |
                            allow / flag / block / shun

When a request hits your ingress proxy, CRS evaluates it at high paranoia:

  • Clean Traffic (Anomaly Score 0): Squeaky clean. Passes through to the upstream application without touching the model (0 ms penalty).
  • Blatant Catastrophes (Anomaly Score 50+): Textbook sqlmap automated sweeps. Centinela triggers a hard block and terminates the request immediately (0 ms penalty).
  • The Grey Zone (Anomaly Score 5–25): Ambiguous traffic that tripped an alarm because a password had single quotes, or a JSON payload contained code. Centinela intercepts it.

Centinela packages the raw request along with the exact regex rules that fired and hands them to Laya with explicit instructions: "Here is the request, and here are the rules that fired. These are investigative leads, not gospel. Did the attacker actually exploit something, or is this just someone pasting an SQL snippet into a support ticket?"


2. The Engineering Journey: Testing Jev, Qwen & Gemma (and Why We Chose Laya)

When we set out to build Centinela, our initial instinct was the same as any engineering team: test the existing off-the-shelf and open-source models first before building our own.

We tested Jev. We hooked up Qwen in Decision mode (running through our custom parallel-decision engine on llama.cpp). We tested Gemma in Decision mode as well.

The results from that testing phase were eye-opening:

  • Too Slow for Inline Defense: Running generative decoders like Qwen 27B inside the live request path added 760ms+ of latency. For production web applications handling interactive traffic, that is an unacceptable latency tax.
  • Accuracy & Calibration Deficits: General-purpose models struggled with the exact threat calibration we needed. Gemma, for instance, produced polarized 0.0 or 1.0 confidence outputs, obliterating the nuanced thresholding required to separate benign code from true exploits. Jev and Qwen had accuracy tradeoffs on our specific threat distributions that didn't meet our bar.
  • Privacy & Data Sovereignty: Shipping sensitive customer request bodies (often containing passwords, session cookies, or personal data) to third-party cloud APIs was an architectural non-starter.

The conclusion was clear: general-purpose conversational LLMs forced into network proxies are the wrong tool for the job. You don't need a model that can write poetry; you need a model laser-engineered for classification at wire speed.

🎯
The Pivot: Enter Laya So we went with Laya. We took a fast, multilingual encoder (322M parameters, mmBERT-base) and fine-tuned it specifically on our curated datasets. By training it directly on real-world attack vectors, benign edge cases, and the exact typed hazard battery Centinela evaluates, we achieved sub-40ms speeds and surgical accuracy. From there, Laya was put directly in place to use in production.

Laya runs packaged inside our lightweight laya-serve container. Instead of burning GPU cycles generating tokens, Laya is laser-focused on answering Centinela's fixed battery of typed hazard questions: sqli, xss, command_injection, path_traversal, ssrf, recon, and a calibrated 4-level severity score.

Because request states can extend to roughly 1,600 tokens (including HTTP headers, body excerpts, and matched CRS rule metadata), Laya operates with a 2,048-token context window. On an AMD Radeon RX 7900 XTX, Laya delivers a blistering 39 ms p50 / 79 ms p99 latency—fitting comfortably within Centinela's default 150ms inline deadline budget.


3. The Request Pipeline: The Fastest Funnel in Security

Even with a 39ms model, you shouldn't call it on every request. Centinela uses a strict cheapest-first execution funnel:

  1. Shun List Check: Has this client IP already earned a ban or repeated blocks? Dropped in memory (μs).
  2. IP Reputation & Blocklists: Checks Spamhaus DROP and FireHOL netsets directly (μs).
  3. Rate Limiting: Sliding-window client request limits (μs).
  4. Bypass Prefixes: Health checks (/healthz, /favicon.ico) skip inspection entirely (μs).
  5. Embedded CRS Scoring: Evaluated by Coraza and OWASP CRS in Detection-Only mode (sub-ms).
  6. Hard-Block Check: Astronomical WAF scores drop right here with zero model invocation (μs).
  7. Verdict Cache: Hashes the payload semantics + WAF findings (IP-agnostic). If a botnet sprays the same exploit across 5,000 rotating IPs, only request #1 hits Laya; the other 4,999 hit the cache in 5 μs.
  8. The Gate: Only requests meeting CENTINELA_GREY_MIN proceed.
  9. Laya Model Adjudication: Parallel evaluation within the 150ms budget. If Laya misses the budget, Centinela fails open (FAIL_OPEN=true) to protect user experience, but leaves the evaluation to finish in the background to shun repeat offenders on subsequent requests.

4. The Numbers: Evaluating the Grey Zone

To measure the real tradeoff, we built an automated evaluation harness (cmd/centinela-eval) and tested a 68-request probe set (29 attacks of varying subtlety, 39 benign-but-scary edge cases) against CRS 4.25 via Coraza 3.8, comparing CRS alone against the models we tested:

Pipeline Attack Detection False Positives FP Rate Latency (p50 / p99)
CRS PL1 Alone 82.8% 9 / 39 23.1% —
CRS PL2 Alone 82.8% 17 / 39 43.6% —
CRS PL3 Alone 82.8% 20 / 39 51.3% —
CRS PL3 + Laya 82.8% 7 / 39 17.9% 39 / 79 ms (RX 7900 XTX)
Tested: CRS PL3 + Qwen 27B (Decision Mode) 86.2% 4 / 39 10.3% 766 / 1436 ms (Too slow)
Tested: CRS PL3 + Gemma 12B (Decision Mode) 86.2% 13 / 39 33.3% 955 / 2474 ms (Uncalibrated)

The numbers demonstrate why dedicated fine-tuning wins:

  • False Positives Plummet from 51.3% to 17.9%: CRS PL3 by itself erroneously blocked 20 benign requests out of 39. Laya cleared nearly two-thirds of those false alarms immediately, dropping the false positive rate to 17.9% while keeping attack detection intact at a lightning 39ms response time.
  • The Speed Advantage: At 39ms, Laya is nearly 20× faster than Qwen 27B and 24× faster than Gemma 12B, making real-time inline evaluation practical on commodity GPUs.
  • Full Data Sovereignty: Unlike cloud APIs that require public network transit and token fees, Laya runs entirely in-cluster. Your sensitive customer traffic never leaves your infrastructure.

5. Where Centinela & Laya Excel

  • Enabling Paranoia Level 3: Unlocks deep inspection without breaking logins, code repositories, or rich client applications.
  • Repeat-Offender Shunning: Scanners rarely send one massive exploit; they send 40 tiny probes. Centinela tracks per-client block frequency over a sliding window (CENTINELA_SHUN_AFTER) and drops the hammer on persistent attackers.
  • Flexible Topologies: Deploys as an HTTP forward_auth target behind Nginx, Caddy, or Traefik, OR in-path as a reverse proxy for Cloudflare Tunnels where no dedicated ingress controller exists.
  • Domain-Tuned for Web Security: Fine-tuned across curated datasets including real attacks from SR-BH 2020 and normal traffic from CSIC 2010, tailored specifically for web security hazards.

6. What We Are Improving Next (The Engineering Roadmap)

We believe in radical transparency about Centinela and Laya's current engineering boundaries:

A. Retraining Laya on High-Volume Traffic

While curated training datasets gave Laya a strong foundation, subtle reconnaissance probes (like /actuator/env or /phpmyadmin) without matched WAF rules remain an area for refinement. Our active plan deploys Centinela under high-volume traffic behind Cloudflare (leveraging Cloudflare Tunnels routing directly to Centinela's in-path reverse proxy) to collect real-world traffic logs via CENTINELA_TRAIN_LOG, followed by an iterative retraining round and ONNX/runtime compile acceleration to push latency even lower.

B. The Adversarial Input Paradox

In a model-driven IPS, the payload being evaluated is written by the adversary. While Centinela wraps payloads in strict delimiters and instructs Laya to treat request bodies as opaque data, prompt injection remains an active research frontier. Keeping CRS at the front line ensures that blunt, signature-heavy exploits never reach the model.

C. Schema & Field Awareness

Today, Centinela inspects raw serialized key-value pairs. Teaching Centinela to understand that a field named password is allowed to look chaotic, while id must be an integer, will eliminate the remaining residue of false alarms.

D. Distributed Cluster State

Currently, verdict caches and shun tables live in local memory per pod. We are working on cluster synchronization via Redis or gossip protocols so a shun triggered on pod A instantly protects pods B through Z.


Summary

Centinela isn't about replacing proven network engineering with generative AI hype. It's about deploying a fast, specialized 322M encoder fine-tuned specifically for intrusion detection exactly where traditional regexes fail: in the messy, ambiguous grey zone where human intent matters.

By pairing OWASP Core Rule Set's blazingly fast heuristic filtering with Laya's calibrated contextual decision-making, we get the best of both worlds: maximum paranoia with minimal disruption.

📦
Open Source & Available Now Centinela is licensed under GPL-2.0 and developed by the ColibriSec team.
Repository: git.colibrisec.org/colibrisec/centinela

Read more

Brecha de Datos Médicos en Photon Health

Filtración en Photon Health: Zero-Day de Inyección SQL en Metabase Expone Recetas Médicas de Pacientes

📌Security Roundup Series: Semana del 9 de Octubre de 2026 • 4 min read deep dive🏛️Incident Overview: Target / Organization: Photon Health, Inc. (Plataforma de Prescripción Médica Digital) Threat Actor / Attribution: Actor Desconocido (Extorsión Financiera) Impact / Records Compromised: Nombres de pacientes, direcciones, números de teléfono, fechas de nacimiento, recetas médicas completas

By James Luther