Skip to content

Fix security, stability, and performance quick wins - #193

Open
Sparksx wants to merge 1 commit into
mainfrom
claude/focused-curie-b0poa5
Open

Fix security, stability, and performance quick wins#193
Sparksx wants to merge 1 commit into
mainfrom
claude/focused-curie-b0poa5

Conversation

@Sparksx

@Sparksx Sparksx commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Summary

Comprehensive codebase audit covering security, performance, stability, and functionality. This PR implements the 9 highest-priority quick wins identified (high impact, low effort).

Security fixes

  • JWT algorithm pinning: All jwt.verify() calls now specify { algorithms: ['HS256'] } to prevent algorithm confusion attacks (alg: none)
  • Rate-limit /refresh endpoint: Added authLimiter (5 req/min) to POST /api/auth/refresh — previously only had the global 100 req/min limit
  • Settings key whitelist: PUT /api/auth/settings now only accepts known keys (theme, language, soundEnabled, musicEnabled, notifications), preventing prototype pollution and oversized data storage
  • Admin dashboard XSS hardening: Escaped role names interpolated into CSS class attributes and sanitized sprite sheet URLs in style attributes

Stability fixes

  • Atomic clan leave + ownership transfer: Wrapped the member delete and ownership reassignment in a single Prisma interactive transaction — a crash between the two operations previously left clans with an invalid ownerId
  • Atomic refund gold clawback: Combined purchase.status update and gold deduction into one transaction — previously a crash after marking "refunded" but before deducting gold let players keep both
  • Save-on-unload with keepalive: Tab-close/hide save now uses fetch() with keepalive: true instead of apiFetch(), so the browser completes the request even as the page is discarded

Performance fixes

  • Lightweight clan listing query: GET /api/clans now uses a minimal include (equipment only for power calculation) instead of loading full member profiles, PvP stats, and timestamps for all members of 25 clans
  • Cache-Control headers: Added Cache-Control: public, max-age=3600 to monster templates and sprites endpoints (matching the existing equipment/player template headers)

Test plan

  • All 524 tests pass (npm test)
  • Zero lint errors (npm run lint — 53 pre-existing warnings only)
  • Production build succeeds (npm run build)
  • Verify clan leave works correctly (owner transfer + disband)
  • Verify settings endpoint rejects unknown keys
  • Verify clan listing page loads with correct power totals

Generated by Claude Code

Security:
- Pin JWT algorithm to HS256 in all verify calls (defense against alg confusion)
- Rate-limit the /api/auth/refresh endpoint with authLimiter
- Whitelist allowed keys in PUT /api/auth/settings (prevent prototype pollution)
- Escape interpolated values in admin dashboard innerHTML (role classes, sprite URLs)

Stability:
- Wrap clan leave + ownership transfer in a single Prisma transaction
- Make refund gold clawback atomic with purchase status update
- Use keepalive: true for save-on-unload fetch so browsers don't cancel it

Performance:
- Use lightweight include for clan listing (skip full member equipment)
- Add Cache-Control: public, max-age=3600 to monster templates and sprites endpoints

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LEkog6b5fHokF9F6nqWmPU
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants