What's New in v2.4
v2.4.0 is about evidence. The WAF's accuracy is now measured, and CI pins it. Defaults that relied on a secret published in the source are gone. Personal data stays out of AI prompts. The audit log can prove it hasn't been edited. Full details are in CHANGELOG.md.
Read before upgrading to v2.4.0
- Dashboard sessions end on restart unless
Dashboard.SecretKeyis set. - The default password works only from localhost.
- AI features see redacted data.
See the upgrade checklist.
Security fixes
- Double encoding bypassed the WAF. 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. - No published JWT secret. An unset
Dashboard.SecretKeyused a value from the source code, so anyone could forge an admin token outside release mode. It now defaults to a random secret generated at each start. - The default password works from localhost only. This means a direct loopback connection with no forwarding headers.
AllowInsecureDefaultsopts back in. - Same-origin WebSocket. The live threat stream accepted browser handshakes from any origin.
- IP blocks work with the WAF disabled. They used to be enforced only inside the WAF middleware.
Measured WAF accuracy
Two corpora in the repository, 89 legitimate-but-suspicious requests and 56 attacks, measure the built-in patterns at every sensitivity level. CI fails if a change adds false positives or misses. With the default rule set:
- 9 of 89 false positives (10%), down from 32 of 84 (38%)
- 56 of 56 attacks detected, up from 47 of 51
See Measured Accuracy. An attack regression suite also runs end to end:
- encoded payloads are blocked
- spoofed forwarding headers don't reset a rate limit or get out of an IP block
- credential stuffing still gets locked out
security/scan runs ZAP and sqlmap against a deliberately injectable app.
AI redaction, on by default
Before anything is sent to the AI provider:
- query values are masked and request bodies are dropped
- IPs are truncated (the last IPv4 octet; IPv6 down to its /48)
- emails, tokens, card numbers, and secrets are scrubbed
The matched attack fragments are kept, so analyses still see what triggered a detection. AI.Redaction opts back out, field by field. See AI Analysis.
Tamper-evident audit log
Every audit entry is linked into a hash chain as it is stored. GET /api/audit-logs/verify reports:
- modified entries
- deletions
- broken links
The dashboard's Audit page runs the same check through its Verify integrity button. Set Storage.AuditKey for an HMAC chain that someone with database access can't recompute. See Audit Logging.
Live IP reputation and blocklist feeds
Attacking IPs are checked against AbuseIPDB as threats arrive, within a daily quota, and AutoBlock finally acts on them. IPReputation.Feeds downloads blocklists such as Spamhaus DROP and blocks their ranges. Feeds work without an API key. See Threat Intelligence.
Dashboard
- The WAF page changes the mode and each category's sensitivity on the running WAF.
- IP blocks take a lifetime, from 1 hour to 30 days, or can be permanent.
- The Audit page verifies the hash chain.
Upgrade checklist
- Set
Dashboard.SecretKeyto at least 32 random bytes. Otherwise sessions end on every restart, and tokens don't work across replicas. - If you reach the dashboard through Docker, a tunnel, or a reverse proxy, set
Dashboard.Password. The default password is refused there. - Set
Storage.AuditKeyso the audit chain is keyed. - If you need raw payloads in AI analyses, set
AI.Redaction.SendPayloads. - Patterns changed. Run the WAF in log mode for a while and review the Threats page before going back to block mode. OpenRedirect now fires only on parameters named for a redirect.
- Add
IPReputation.Feeds(for example, Spamhaus DROP) to block known-bad networks for free.