flowchart LR
subgraph KERNEL["kernel plane"]
xdp["eBPF shield<br/>XDP + TC"]
maps["maps<br/>ACL · verdict cache · ban table"]
end
subgraph USER["userspace plane"]
lad["detection ladder<br/>S0-S6"]
end
gw["Gateway API<br/>(NGF reference)"] --> lad
lad --> app["app pods"]
xdp --- maps
lad -- verdicts --> otel[("OTLP<br/>trishula.verdict.v1")]
Trishula
An eBPF-native, developer-first Web Application and API Firewall for Kubernetes
Status: research / pre-alpha. Design is specified in the PRD (v4) and the research paper; implementation starts from zero, tracked as TR-01 … TR-36. Nothing here should be presumed working yet. This is research for adoption — not a product pitch.
Intro
Trishula is an open Web Application and API Firewall for Kubernetes that operates at kernel altitude while preserving the full userspace detection stack. One sentence: the WAF is the last security control that never crossed to developer ubiquity — Trishula brings it across. Three components, two planes, one decision record per request.
Objectives
- Adoptability as a first-class feature — CRD-driven policy, per-route promotion gates (learn → shadow → enforce), verdict telemetry a developer can actually read. The people who own the app own its protection.
- Full detection stack at kernel altitude — negative signatures, positive security, bot mechanisms and behaviour bans, backed by an eBPF enforcement point no middleware chain can offer.
- Parity before novelty — OWASP CRS runs via embedded Coraza as the reference evaluator; a CI-blocking differential suite proves the engine matches it, always.
- Honest engineering — fail-open defaults, evidence records for every ban, exit criteria that report pass/fail as measured.
Why this project
Three curves converge, and each alone is an optimization. Together they are an opening:
- Gateway API consolidation — Kubernetes ingress is standardising on the Gateway API; the edge is being re-plumbed right now, and the WAF’s integration point is up for grabs.
- eBPF maturity — kernel-altitude packet processing is dependable, inspectable and CO-RE portable; enforcement does not need to live in a middleware hop.
- AI traffic at the WAF’s front door — agents, scrapers and automated abuse hit exactly the layer the WAF inspects; they mint fingerprints machines cannot hide behind, and they arrive faster than hand-written signatures can follow.
Negative signatures alone cannot carry a modern estate: too much good traffic to risk, too slow to maintain by hand. That is the reason for the project — and why the emphasis is positive security, fingerprinting and behaviour analysis with signatures as one (important) stage among several.
The WAF problem
A web application firewall inspects HTTP conversations and decides: allow, block, rate-suppress or tag. The classic estate runs it in three shapes — an appliance at the edge, a module inside the reverse proxy (ModSecurity-lineage), or a sidecar/car next to the app. Each shape keeps the decision point outside the packet path’s cheapest altitude, and each inherits the middleware’s latency, scaling and failure behaviour.
What a WAF must decide today:
- known-bad requests — signature sets (OWASP CRS) remain the base layer;
- policy violations — the request uses the API in ways its OpenAPI spec forbids (positive security);
- automation posing as users — TLS/HTTP fingerprints (JA4), header order, value entropy, behavioural cadence;
- abuse patterns — rate anomalies and repeat-offender behaviour needing temporary bans;
- new attack classes — LLM/agent traffic shapes that no signature has seen yet.
Traditional deployments answer these with a negative-signature engine and hope. The cost is well known: false positives that block good users, rules maintained by specialists, and telemetry a developer cannot read. Trishula’s answer is structural: keep CRS as one stage, add the positive/fingerprint/behavioural stages, and move the cheapest decisions to the kernel — with every verdict emitted as OpenTelemetry.
Kubernetes deployment
flowchart TB
subgraph cluster["Kubernetes cluster"]
subgraph gwplane["gateway plane"]
ngf["NGF (Gateway API)"]
end
subgraph wafplane["Trishula"]
eng["engine deployment<br/>(plain backend Service)"]
opr["operator<br/>(WAFPolicy / BanPolicy CRDs)"]
sh["shield DaemonSet<br/>(XDP/TC eBPF)"]
end
app["application pods"]
end
clients["clients"] --> ngf
ngf -- HTTPRoute --> eng
eng --> sh
eng --> app
opr -- bundles + map pre-seed --> eng
opr -- pinned maps --> sh
- Install order: operator → shield (DaemonSet) → engine. The operator reconciles
WAFPolicy/BanPolicyCRs into compiled engine bundles (double-buffered) and pre-seeds shield maps. - Gateway API integration: the gateway steers to the engine as a plain backend (HTTPRoute); NGF is the reference data plane — the whole reference stack is OSS. Conformant alternatives (Envoy Gateway, Istio, Traefik, Emissary, kgateway) attach the same way; an
ext_procwire-contract variant for Envoy-family estates is feature-gated for later. - Fail-open by default: an inline shaper must never become the outage;
failureModeis explicit and audited per policy. - Rollback: a CRD-recorded re-pin of the previous bundle — never a hand-hack.
- Node requirements: kernel ≥ 5.8; the shield is CO-RE and verifier-checked in CI.
- Telemetry: every verdict is an OTLP span + metric + log on
trishula.verdict.v1; dashboards ship in-repo.
Detection ladder (short-circuit ordered): S0 kernel pre-clear (ACL, verdict cache, ban table) → S1 cache re-check → S2 CEL rules (cost-budgeted) → S3 OWASP CRS via embedded Coraza → S4 OpenAPI positive security → S5 rate limits → S6 bot fingerprints and behavioural windows. ScoredWindowBan turns repeated abuse into kernel-enforced temporary bans, evidence-recorded, prefix escalation off by default.
Roadmap
Work is tracked on the Trishula — Roadmap & Build Board (org Project) as issues TR-01 … TR-36 in the trishula repo. Every issue lands a runnable artefact with an exit criterion — prove the ladder end-to-end, not slide-by-slide.
| Milestone | Items |
|---|---|
| v0.1 | TR-01–TR-14: repo seed, CEL seed, shield PoC, ingest, ladder slice, NGF lab, CRS differential, operator/CRD, ban shadow + enforce, OTel, bots v0, positive v0, honest exit |
| v0.2 | TR-15–TR-26: HTTP/2+gRPC, Vectorscan, CEL hot reload, OpenAPI learn, behavioural bots, rate-limit ladder, ONNX scorer, ext_proc, DX gate, bench, multi-tenancy, Envoy lane |
| v0.3 | TR-27–TR-36: academy, HTTP/3 + PQ posture (evaluation only), behavioural DoS, DPU, multi-arch, residue gate, composition watch |
Contributions welcome: pick an issue labeled complexity:starter or any area:* that suits you; the referenced PRD section in the issue body is the design source. Branch + PR against trishula-dev/trishula (Apache-2.0).
Reasoning: why these specific choices
- eBPF (XDP first, TC alongside) — the only mechanism that gives kernel-altitude, programmable, verifiable packet policy on stock Kubernetes nodes; CO-RE keeps builds portable. The drop happens where the packet arrives; a middleware chain cannot offer that.
- Gateway API + NGF as reference — Gateway API is where Kubernetes ingress is consolidating; NGF keeps the whole reference deployment OSS and mirrors the topology operators already run. Envoy-family estates get the feature-gated
ext_procvariant later; lock-in to one data plane is not a goal. - Embedded Coraza, not a rule-engine rewrite — CRS compatibility is the adoption surface; embedding buys exact parity by construction (the same parser semantics), and the differential suite keeps a from-scratch fast path honest when it arrives (Vectorscan hot subset, behind a shadow gate).
- CEL for the first-class DSL — typed, cost-budgeted evaluation, Kubernetes-native ergonomics, and a compile step the CRD pipeline can gate on cost before load; a general regex DSL alone cannot offer bounded evaluation cost.
- OpenAPI positive security with promotion gates — the developer-first path: specs exist in repos already; learn → shadow → enforce makes adoption incremental instead of a big-bang policy cutover.
- ScoredWindowBan over naive counters — fail2ban-style bans with an algorithmic scoring window, evidence per ban, prefix escalation off by default: shared-egress false positives are the practical ban killer.
- OpenTelemetry as the verdict contract — every verdict a correlated span+metric+log; security that cannot show its work cannot be adopted by developers.
- fail-open by default — an inline kernel shaper must never become the outage;
failureModeis explicit and audited per policy.
Paper
The arXiv-style paper (“Trishula: An eBPF-Native, Developer-First Web Application and API Firewall for Kubernetes”) is the research companion to this site: the adoptability thesis, the honest field survey (Coraza, ModSecurity, SafeLine, open-appsec, CrowdSec, fail2ban, the eBPF cousins) with the feature-coverage matrix, and the adoption plan. A public link lands here when the paper is archived; until then it travels with the project docs.
