Repository navigation
v2.4.0 — Measured WAF accuracy, no published secrets, AI redaction, tamper-evident audit log
Evidence and hardening. The WAF's accuracy is measured and pinned in CI. There is no published dashboard secret. AI prompts are private by default. The audit log can prove it wasn't edited.
Security fixes
- Double-encoding WAF bypass. The classifier decoded query values once, so
%2527reached an app that decodes again as an apostrophe. Leftover percent-encoding in the path, parameter names and values, and bodies is now decoded up to two more times, and every layer is scanned. Form-encoded bodies are decoded too. - Published JWT secret. An unset
Dashboard.SecretKeydefaulted to a value from the source, so anyone could forge an admin token outside release mode. It is now random, generated at each start. - Default password.
admin/sentinelis accepted only from a direct loopback connection with no forwarding headers, unlessAllowInsecureDefaultsis set. - WebSocket origin. Browser handshakes must now come from the dashboard's own origin.
- IP blocks with the WAF disabled. They did nothing. They are now enforced.
- Memory store data races. Shared actor and threat pointers are now copied.
Measured WAF accuracy
The corpus holds 89 legitimate-but-suspicious requests and 56 attacks. With the default rule set:
- false positives: 9/89 (10.1%), down from 32/84 (38%)
- attacks detected: 56/56, up from 47/51
Patterns that fired on ordinary English and code now need SQL, shell, or URL shape. See Measured Accuracy.
An attack regression suite runs end to end: encoded payloads, spoofed forwarding headers against rate limits and IP blocks, and credential stuffing against AuthShield. security/scan runs ZAP and sqlmap against a deliberately injectable app.
Added
- AI redaction, on by default (
AI.Redaction). Query values, bodies, full IPs, cities, emails, tokens, card numbers, and secrets never reach the provider. Matched attack fragments are kept. - Tamper-evident audit log. Entries are hash-chained, with HMAC when
Storage.AuditKeyis set.GET /api/audit-logs/verifyand the dashboard's Verify integrity button report modified, missing, and relinked entries. - Live IP reputation. Attacking IPs are checked against AbuseIPDB as they arrive, within
MaxChecksPerDay, andAutoBlockacts on the results. - Blocklist feeds (
IPReputation.Feeds). Spamhaus DROP, FireHOL, and NDJSON CIDR lists are refreshed daily and blocked. - Dashboard.
- The WAF mode and per-category sensitivity controls, and a lifetime for each IP block.
- The audit chain verification described above.
Upgrading
- Set
Dashboard.SecretKey(32+ random bytes). Otherwise sessions end on every restart and don't work across replicas. - If you reach the dashboard through Docker, a tunnel, or a proxy, set
Dashboard.Password. The default password is refused there. - Set
Storage.AuditKeyfor a keyed audit chain. - If you need raw payloads in AI analyses, set
AI.Redaction.SendPayloads. - Patterns changed, so run the WAF in log mode briefly and review the Threats page. OpenRedirect now fires only on redirect-named parameters.
Full details are in CHANGELOG.md. Upgrade notes are in What's New in v2.4.