A fast, low-memory Web Application Firewall delivered as a Traefik plugin.
Status: v0.4.5 released. The current release includes audit labels, webhook relay delivery, signed artifacts, SBOMs, Helm OCI packaging, Kustomize overlays, an O(1) reputation limiter, bounded percent-decode-to-fixpoint normalization, an expanded signature pack, User-Agent SQLi suffix probing, over-cap body-prefix inspection, an offline config validator, relay SSRF hardening, optional relay admin auth, and new fuzz targets. v0.4.5 keeps WAF behavior compatible while bounding repeated signature findings, accelerating large reputation deny lists, supervising the relay task graph, accepting documented deny-list address forms, consolidating the relay's random-number dependency, and strengthening benchmark isolation. See CHANGELOG.md for the full list, THREAT_MODEL.md for what the WAF is and is not designed to catch, and docs/configuration.md for the Middleware config reference. The webhook protocol contract lives in docs/webhook-protocol.md.
purple-wolf inspects every HTTP request reaching a route protected by one
of its Middlewares and either lets it through or returns 403 Forbidden.
Inspection covers headers, URL, query parameters, and the request body (up
to a configurable cap) using a hybrid engine: libinjection (SQLi/XSS),
aho-corasick literal signatures, structural anomaly checks, and per-IP
rate limiting / deny-listing.
internet → Traefik (TLS, routing, your existing setup)
└─ compiles purple-wolf.wasm with wazero's shared cache
└─ for each request matching a route that chains a
purple-wolf Middleware:
borrow a guest instance from the host pool
→ normalize → inspect enabled groups → decide policy
→ emit noteworthy audit line
→ block with 403 or restore the body and call backend
- Three crates:
purple-wolf-core(the engine, pure Rust, native +wasm32-wasip1),purple-wolf-traefik(http-wasm guest plugin), andpurple-wolf-relay- a standalone webhook fan-out service that tails Traefik's audit-log stream and delivers HMAC-signed events to subscribers. - Multi-tenant by construction: each
Middlewareconfig creates a separate host middleware. The http-wasm host pools guest instances for concurrency; every guest has independent WASM memory, immutable config, detector state, and reputation buckets. - Push delivery: the WAF stays focused on detection; if you want signed webhooks to a SIEM, Slack, or per-tenant subscriber, run the relay alongside Traefik. See the relay's README and the webhook protocol spec.
Run Traefik, the WASM plugin, a backend, the relay, and an HMAC-verifying subscriber:
docker compose -f examples/demo/docker-compose.yml up --buildThen try the requests in examples/demo/README.md.
Install the OCI Helm chart in monitor mode:
helm install purple-wolf oci://ghcr.io/guaracloud/charts/purple-wolf \
--version 0.4.5 \
-f charts/purple-wolf/values.monitor.yamlKustomize users can start with:
kubectl apply -k deploy/kubernetes/overlays/monitor-modeThe chart and Kustomize overlays render monitor/enforce Middleware examples but
do not attach them to any route. Attach purple-wolf-monitor to selected
IngressRoutes first, review audit output, then opt in to enforce mode.
Before production use, verify checksums, Cosign signatures, SBOMs, image digests, and the release manifest:
gh release download v0.4.5 --repo guaracloud/purple-wolf --dir purple-wolf-releaseFollow docs/release-verification.md and deploy
digest-pinned image references from release-manifest.json.
Run the relay when you want signed webhooks to a SIEM, Slack bridge, or tenant
subscriber. See docs/operations.md,
docs/helm.md, and
docs/kubernetes-production.md.
For the full per-field Middleware reference, see
docs/configuration.md. Existing raw files under
examples/ remain educational examples; production users should
prefer Helm or Kustomize.
Same Kubernetes topology, same Traefik v3.1, same backend, same 200 m CPU / 1 GiB resource budget, same OWASP CRS corpus - only the WAF engine differs. Two rounds; round 2 expanded the matrix to a no- WAF baseline pod, a ramp-to-break sweep, 12 CRS attack classes (4 536 vectors), a 10-minute soak with resource sampling, and a small functional robustness suite.
Headline results (full methodology + tables + caveats in
docs/benchmark.md):
- Isolated WAF overhead: +0.1–0.2 ms p99 vs a Traefik-only baseline pod. Invisible at typical backend latencies.
- Sustained throughput at the same resources: purple-wolf is clean to ~8 000 RPS; Coraza http-wasm collapses at 500 RPS. About 16–20× more sustained RPS for purple-wolf at the tested ceiling.
- Detection across 12 CRS rule classes (4 536 vectors): purple-wolf 14.55 % overall TPR vs Coraza inline-PL1 6.11 % - 2.4× more attacks blocked, with 0 % FPR on the benign corpus for both. Java (+26.5 %), RCE (+6.3 %), XSS (+5.1 %) are the biggest margins.
- Memory under sustained load: stable in an 80–96 MiB band over a 10-minute soak at 1 000 RPS, no drift. Coraza peaked at 946 MiB during round 1 (OOM-killed five times at the original 512 MiB ceiling).
- Closed benchmark-surfaced gaps: round 2 found misses for
User-Agent SQLi with a
Mozilla/prefix and bare;wgetquery payloads. v0.4 closes both with the UA suffix probe andrce_cmdsignatures; the benchmark numbers above remain the last published live-stack run, so a rerun is still needed to publish updated live-stack coverage.
The benchmark is reproducible end-to-end:
benchmarks/runner/round2/run-all-round2.sh.
Raw JSONL + CSV outputs from the published runs live under
benchmarks/results/.
What the benchmark is not: a claim that purple-wolf is "better" than Coraza. Coraza's native (Go-binding) Traefik integration is faster and rule-richer than the http-wasm path measured here, and full OWASP CRS catches far more atomic-token tests than either engine in this comparison - at higher FPR. The comparison is honestly bounded: same plugin shape, same resource ceiling, same yardstick.
cargo fmt --all --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace --all-targets
cargo test --workspace --doc
cargo deny check
cargo build -p purple-wolf-traefik --target wasm32-wasip1 --releaseWASM builds require wasi-sdk. To use the repository's cross-platform Docker
builder (including on arm64 hosts):
mkdir -p target/wasm-docker
docker build -f examples/demo/Dockerfile.wasm-builder -t purple-wolf-wasm-builder .
docker run --rm -v "$PWD/target/wasm-docker:/out" purple-wolf-wasm-builderFor a native toolchain install, download wasi-sdk and set its root:
# Download wasi-sdk from https://github.com/WebAssembly/wasi-sdk/releases
export WASI_SDK_PATH=/path/to/wasi-sdkDual-licensed under MIT OR Apache-2.0. libinjection (vendored C) is BSD-3-Clause.