What's New in v2.1 – v2.3

The releases since v2.0.0 share one theme: configuration and dashboard controls that compiled, read as correct, and silently did nothing. v2.2.0 added a way to detect that class of bug; v2.2.2 fixed security holes found while auditing for it; v2.3.0 made the remaining dead settings work. Full details are in CHANGELOG.md.

Read before upgrading to v2.3.0

Rate limits become a real sliding window, audit logs are kept for a year, and compliance reports on in-memory storage are refused in release mode. See the upgrade checklist.

v2.3.0 — settings that did nothing now work

Dashboard edits reach the running middleware

Changing the WAF mode or rules, route rate limits, or alert severity from the dashboard used to update only the API server's copy of the config — enforcement never changed while the dashboard showed the new values. Those edits now apply to live requests immediately, are validated (bad input returns 400 and changes nothing), and are audited. They are not persisted: a restart returns to your configured values.

WAF sensitivity, rule actions, and rate-limit strategies are enforced

  • WAF.Rules levels were never read. RuleOff, RuleLow, RuleMedium, and RuleStrict now change detection — see Strictness Levels. The defaults keep every pattern.
  • WAFRule.Action: "log" records a custom rule's matches without ever blocking, even in block mode — watch a new rule against real traffic before trusting it.
  • RateLimit.Strategy was never read; every limit was a fixed window. SlidingWindow (default), FixedWindow, and TokenBucket are now real — see How It Works.

User activity is recorded

Config.UserExtractor was never read, so no user activity was stored — the Users page, the GDPR report's per-user section, and anomaly detection all saw nothing. It now records one entry per authenticated request.

1UserExtractor: func(c *gin.Context) *sentinel.UserContext {
2 claims, ok := c.Get("claims") // set by your auth middleware
3 if !ok {
4 return nil // anonymous: not recorded
5 }
6 u := claims.(*MyClaims)
7 return &sentinel.UserContext{ID: u.Subject, Email: u.Email}
8},

An audit trail for Sentinel itself

Every dashboard action — IP blocks, WAF and rate-limit changes, custom rules, lockout releases, threat triage — and every login (dashboard logins, and app logins AuthShield observes) is an audit entry. Audit logs keep their own retention, Storage.AuditRetentionDays, default 365. See Dashboard Actions and Logins.

Honest compliance reports

Every report carries a provenance block — storage driver, durability, retention, oldest records, and warnings when the data can't support the report. Reports on in-memory storage are refused in release mode. The SQLite and Postgres user and analytics queries, which were stubs returning nothing, are implemented. See Compliance Reports.

v2.2.2 — security fixes

  • Client IP spoofing behind a proxy. The leftmost X-Forwarded-For entry — which the client writes — was trusted. The chain is now read right to left past your WAF.TrustedProxies.
  • Dashboard login brute-force limit could be reset by rotating X-Forwarded-For; it now uses the same trusted-proxy logic.
  • SQL injection via sort_by on threat listings (SQLite / Postgres) is closed by an allowlist.
  • SSRF client bypasses[::], NAT64 / 6to4-embedded internal addresses, zoned and IPv4-mapped IPv6 literals, Oracle Cloud metadata, trailing-dot metadata hostnames — are blocked, and AllowedHosts works for internal hosts.
  • Compliance report counts — PCI-DSS blocked threats filtered on the wrong field; SOC 2's blocked count could never exceed 1.

v2.2.0 — ValidateConfig

sentinel.ValidateConfig(cfg) returns every setting that would be silently ignored or would silently disable a feature — unknown storage drivers, unmatchable route patterns, broken custom rules, alert sinks without credentials, and, since v2.3.0, unknown WAF modes, sensitivity levels, rule actions, and rate-limit strategies. Mount logs the findings; call it yourself to fail a deploy.

1for _, issue := range sentinel.ValidateConfig(cfg) {
2 if issue.Severity == sentinel.IssueError {
3 log.Fatalf("sentinel config: %s", issue)
4 }
5}

v2.1.x — WAF false positives and wildcard routes

  • The SSRF pattern no longer matches browser version strings such as Chrome/140.0.0.0, which had blocked every Chromium user in block mode.
  • SQL-injection patterns no longer match opaque tokens or scan headers.
  • WAF.ExcludeRoutes and RateLimit.ByRoute accept wildcard patterns (/v1/*, /api/apps/*/products/**).
  • WebSocket endpoints require a dashboard token; dashboard IP blocks default to 24 hours.

Upgrade checklist

  1. If you run behind a reverse proxy, set WAF.TrustedProxies to its addresses. Blocks keyed on spoofed client IPs stop matching after v2.2.2 — that is the point.
  2. Rate limiting is a sliding window by default from v2.3.0. For the old behavior set Strategy: sentinel.FixedWindow.
  3. If any WAF.Rules category is set to Off, Low, or Medium, check that you still want it — those levels now change detection.
  4. Audit logs are kept 365 days by default. Lower Storage.AuditRetentionDays if disk is tight (PCI-DSS requires 12 months).
  5. Set UserExtractor if you want the Users page, GDPR user data, and anomaly detection.
  6. Remove AI.DailySummary — it is deprecated and never did anything.
  7. Run sentinel.ValidateConfig in CI and treat IssueError as a failed build.

Built with by JB