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.SecretKey is 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 %2527 reached 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.SecretKey used 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. AllowInsecureDefaults opts 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

  1. Set Dashboard.SecretKey to at least 32 random bytes. Otherwise sessions end on every restart, and tokens don't work across replicas.
  2. If you reach the dashboard through Docker, a tunnel, or a reverse proxy, set Dashboard.Password. The default password is refused there.
  3. Set Storage.AuditKey so the audit chain is keyed.
  4. If you need raw payloads in AI analyses, set AI.Redaction.SendPayloads.
  5. 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.
  6. Add IPReputation.Feeds (for example, Spamhaus DROP) to block known-bad networks for free.

Built with by JB