SIGN IN SIGN UP

release: 2.0.56 — security hardening + runtime credential rotation + ban detection + brute-force lockout

# v2.0.55 part — codex audit fixes
- H1 [HIGH] dashboard checkAuth no longer falls back to API_KEY on public bind (privilege escalation closed)
- H2 [HIGH] caller-key XFF spoof guard — TRUST_PROXY_X_FORWARDED_FOR=1 opt-in
- H3 [HIGH] /proxy/global + /proxy/accounts/:id PUT now run assertPublicUrlHost (SSRF closed)
- M2 [MED] tool-call salvage filterToolCallsByAllowlist drops calls whose name isn't in body.tools[]
- L1 [LOW] safeEqualString switched to sha256 + timingSafeEqual (no length oracle)

# v2.0.56 part — research-driven upgrades
Research: CLIProxyAPI / WindsurfSwitch / windsurf-assistant / windsurf-assistant-pub.

- runtime credential rotation: PUT /dashboard/api/settings/credentials lets operators
  change API_KEY and DASHBOARD_PASSWORD from the dashboard UI without redeploying.
  scrypt-derived password hash (zero deps via node:crypto). Dual-skin form added.
- brute-force lockout (CLIProxyAPI-style): 5 dashboard auth failures → 30 min IP ban
  with 429 + Retry-After. Idle entries pruned hourly.
- ban detection (windsurf-assistant-pub-style): 14 patterns (en + zh) match
  Account suspended / API key revoked / 账号已停用 etc. Two strikes within 30 min →
  status='banned' + cascade pool invalidation. Successful chat clears the streak.
  Wired into both stream and non-stream chat error paths.

Tests: 533 → 608 (+75). 8 new test files cover every fix + new feature.

Deployment caveat: this version requires DASHBOARD_PASSWORD set on public binds
(API_KEY no longer doubles as the dashboard password) and TRUST_PROXY_X_FORWARDED_FOR=1
when behind nginx LB (default docker-compose setup). See RELEASE_NOTES_2.0.56.md.

Closes #93 #108 #109 (already verified in production v2.0.54).
D
dwgx committed
b2bda56151b548f299f436a1cf0f4dc07165d06d
Parent: bd2e743