eBPF-native, developer-first Web Application and API Firewall for Kubernetes. kernel shield · userspace engine · control plane
Trishula protects Kubernetes traffic in three planes. The kernel shield runs
verifier-checked eBPF programs. The userspace engine runs the detection
stack: OWASP CRS, CEL rules, OpenAPI positive security, bot fingerprints and
the ban table. The control plane compiles WAFPolicy CRDs into signed policy
bundles. Every verdict is a correlated OpenTelemetry record.
Status: the 2026.01-rc1 component set sits merged on main. The lab
gates run green on a live cluster. The bench harness measures the
§17 walls in CI. The gaps carry their own
list on this page.
Each slice landed as a watched-RED then GREEN leaf PR per AGENTS.md.
| Component | Where | What exists | Evidence |
|---|---|---|---|
| Shield loaders | internal/shield/ |
CO-RE XDP + TC objects (arm64, amd64); Go loaders; fail-closed TierRefusal; tier measure at boot. |
#80 tier run · #10 ban E2E |
| Kernel C + wire | bpf/ |
shield_xdp.c (ACL, verdict cache, ban table), flow_tc.c (ringbuf); wire layouts test-pinned. |
banwire tests in-package |
| Ingest | internal/engine/ingest/ |
ringbuf drain → decode → per-connection assembly; kernel-free. | TR-04d merge |
| Detection ladder | internal/engine/ladder/ |
S0–S5 wiring + verdict vocabulary; HTTP/1 and HTTP/2/gRPC parse. | TR-05 merge |
| OTel telemetry | internal/engine/otel/ |
span + metric + log record, correlated by request id. | #11 evidence |
| Bot fingerprints | internal/engine/botdef/ |
JA4 + header-plane detector; golden vectors. | #99 |
| Positive security | internal/engine/positive/ |
OpenAPI 3.1-subset body gate; fail-closed. | #13 evidence |
| CRS evaluator | internal/crs/ · test/crs-differential/ |
embedded Coraza reference + CI-blocking parity differential. | #7 parity 19/19 |
| ScoredWindowBan | internal/engine/rateban/ |
§13.3 ban with clock seam + evidence; kernel publish. | #10 in-VM E2E |
| Rate algorithms | internal/engine/rateban/ |
token bucket, multi-window sliding, EWMA per §13.2; CRD-selected; Retry-After on every throttle. | #20 RED/GREEN tables in-package |
| Operator | internal/operator/ · api/v1alpha1/ |
WAFPolicy CRD → bundle compile (fail closed) → publish. |
#76 M9 evidence |
| Engine + consult | cmd/engine/ |
transparent proxy; bundle consult; hot reload. | #6 hop evidence |
| DX1 lab | lab/dx1/ · lab/demo.sh |
idempotent bring-up; timed apply→effect; hop verification. | Proof record |
Budgets read off §17.1.
Wall numbers read from the last recorded per-row CI run:
39920698798,
head 24d5be7, before the #150 perf levers. The numbers re-read at each release.
| Cell | Budget p99 | Last build p99 | Verdict |
|---|---|---|---|
| idle-get | 600 µs | 546.7 µs | holds (0.91x) |
| attack-sqli-small | 1500 µs | 828.3 µs | holds (0.55x) |
| attack-xss-small | 1500 µs | 1733.5 µs | unmet (1.16x) — variance class, #147 |
| ladder-json-1k | 600 µs | 548.6 µs | holds (0.91x) |
| ladder-json-8k | 600 µs | 798.7 µs | unmet (1.33x) — variance class, #147 |
| ladder-json-64k | 1200 µs | 577.2 µs | holds (0.48x) |
| ladder-form-dense-1k | 600 µs | 116319.7 µs | pinned open — the §17.1 finding |
| ladder-form-dense-8k | 600 µs | 180720.5 µs | pinned open — the §17.1 finding |
| steady-json-8k (the M2 e2e cell) | 1500 µs | 320.0 µs | holds (0.21x) |
The gate set: test/bench runs the §17.2
recipes in CI. A verdict re-reads per run. Per-row walls print in the job log
when a row breaks the gate; green runs print package lines only.
The §17.1
arg-dense finding stays open: the form rows read ≥194x over budget. The perf
levers (SecRxPreFilter + serialized CI packages) ride
#150. After the levers,
the attack cell reads 0.22–0.31 ms per evaluate on the measurement host.
| Control-plane gate | Budget | Recorded | Verdict |
|---|---|---|---|
| apply→effect (M9) | 5000 ms | 1465 ms and 2618 ms, #76 | holds |
CRS parity: 19/19 corpus cases at 100% verdict parity, one documented skip (#7).
The dev VM walls (#147):
one quiet run on the OrbStack rig (noble, arm64, 8 vCPU, Go 1.26.0), prefilter
off vs on. The pinned
§17.1
finding holds on the VM at 13x-95x (prefilter on). The 64k row
carries a guest-side p99 tail on the VM; hosted CI reads the same row at
0.48x-0.86x and stays the calibration surface.
| Cell | Budget p99 | VM p99 (prefilter off) | VM p99 (prefilter on) |
|---|---|---|---|
| steady-json-8k | 1500 µs | 794.6 µs | 188.8 µs |
| attack-xss-small | 1500 µs | 1039.5 µs | 925.8 µs |
| attack-sqli-small | 1500 µs | 1095.7 µs | 548.3 µs |
| ladder-json-1k | 600 µs | 611.3 µs | 483.3 µs |
| ladder-json-8k | 600 µs | 347.3 µs | 626.6 µs |
| ladder-json-64k | 1200 µs | 9890.9 µs | 14189.2 µs |
| ladder-form-dense-8k | 600 µs | 63354.1 µs | 56770.3 µs |
The list pairs each not-shipped feature with its tracker.
- Inline
< 10 mswalls on the lab plane — the CI harness measures engine-only cells today. - Verdicts on live ringbuf traffic inside cluster pods — a later engine slice.
- HTTP/3 request-path parse — posture evaluation on #29.
- Socket-plane fast path, fast-path compiler, kTLS posture — #51 · #52 · #53.
- trishulactl full CLI surface — the skeleton exists; the surface is a later phase.
- OpenAPI learn mode + promotion gates — #18.
- ML scorer tier — #21.
- Wire-out OTLP export — the triad verifies in-memory today.
- OpenShift + multi-arch + DPU port — #33 · #32.
The board is the Trishula Roadmap.
Layout (the reference implementation)
api/v1alpha1/ CRD types (WAFPolicy, BanPolicy, …)
cmd/ engine, operator, shield, trishula, trishulactl, attackdemo
bpf/ shield_xdp.c, flow_tc.c (CO-RE, bpf2go)
internal/ engine (ingest, ladder, cel, http1, http2, otel, botdef, positive, rateban), operator, shield
manifests/ install manifests (incl. CRD)
lab/ demo.sh · dx1/ · demo-attack.sh · verify-xdp-chain.sh · tier-gate.sh
test/ crs-differential · ban-conformance · banenforce · tier · bench
docs/ spec, paper, academy
bash lab/demo.shThe script brings the DX1 lab up on any Docker-provider host. Needs go,
kubectl, helm, docker and curl. It builds the engine and operator
binaries, applies the policy and runs the timed apply→effect scenario. The
exit banner reads DEMO-OK or DEMO-FAIL. The verbatim recorded output sits
on the issue record above.
bash lab/dx1/dx1-gate.shThe gate asserts: clone → first enforced rule in ≤ 15 min. The nightly job keeps the timing asserted.
go test ./...The suite gates the bench walls, the CRS parity differential (19/19 corpus cases), the ban conformance set, the shield tier gate and the docs guards.
lab/bench-vm.sh runs the §17.2 rig in the dev VM. Start from a VM copy of the tree:
orb run -m trishula-build-dev -u root bash /mnt/mac/<path-to-clone>/lab/bench-vm.shThe script prints four sections: the new CI shape, the old-shape control, the walls with the prefilter on and the control with it off. The VM is the A/B surface. Hosted CI stays the calibration surface.
The verbatim lab/demo.sh output for the Phase 0 exit sits on the recorded
run at main ed9b271. The hop, M9 and parity evidence trails link from the
rows above.
The shield measures what the hook sees (#80). On OrbStack-family pod-veths the attach altitude is not the effective altitude.
| Tier | Meaning | Enforcement posture |
|---|---|---|
full |
every packet at both altitudes (XDP + TC) | full payload visibility at TC |
first_packet |
first packet only (OrbStack pod-veth posture) | ban/ACL on new connections only; sampled flows |
none |
no packets visible | loader refuses and fails loudly (TierRefusal) |
MIT — see LICENSE.