Skip to content

Security, stability and performance quick wins#169

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

Security, stability and performance quick wins#169
Sparksx wants to merge 1 commit into
mainfrom
claude/focused-curie-efkiin

Conversation

@Sparksx

@Sparksx Sparksx commented Jul 2, 2026

Copy link
Copy Markdown
Owner

Summary

Comprehensive audit of the game across security, stability, performance, and functionality — implementing all high-priority quick wins (low difficulty, high impact).

Security fixes

  • Enable CSP headers — was fully disabled (contentSecurityPolicy: false), now enforces a real policy allowing Stripe, Google, Discord, and WebSocket origins
  • Ban check on all auth paths — banned users could still log in via password, Discord, or Google OAuth and access REST APIs; now blocked at login
  • Rate limit on game state save — dedicated 30 req/min limiter on PUT /api/game/state to prevent abuse
  • Username format validation — restrict to [a-zA-Z0-9_-] on register and change-username (was only length-checked)
  • Distinct JWT secrets in devJWT_SECRET and JWT_REFRESH_SECRET had identical defaults, making access/refresh tokens interchangeable
  • Settings payload validation — cap at 20 keys and 200-char values to prevent oversized JSON payloads

Stability fixes

  • Remove competing shutdown handlersprisma.js had its own SIGINT/SIGTERM handlers that raced with the main shutdown() in index.js, potentially exiting before the HTTP server drained
  • Clear intervals on shutdown — token cleanup and combat log intervals are now properly cleared during graceful shutdown
  • Health check verifies DB/api/health now runs SELECT 1 so load balancers detect database outages

Performance fixes

  • Batch expedition rewards — expedition resolution was doing N individual updateMany calls per member; now uses 2 bulk operations regardless of party size
  • Atomic PvP rating updatespvpRating was set directly (losing concurrent updates); now uses { increment: ratingChange } for safe concurrent fights
  • Add missing DB indexChatMessage.senderId index for admin profile lookups
  • Cache-Control on monster templates — static game data now returns max-age=3600 (was missing, unlike equipment/player templates)

Full audit results (not implemented — for future work)

Security (remaining)

Priority Issue
Critical Client-authoritative gold — PUT /api/game/state accepts any gold value
Medium Cosmetic ownership not validated server-side
Medium Admin dashboard served without backend auth check

Performance (remaining)

Priority Issue
High No server-side caching (role checks, templates, mute/ban)
High Clan list over-fetches full equipment for all members
Medium No code splitting — entire game is one JS bundle
Medium Excessive save() calls (4+ per game tick during active play)

Stability (remaining)

Priority Issue
High Clan leave/disband not wrapped in a single transaction
Medium Server accepts requests before seed data loads
Medium No DB connection pool tuning

Functionality (remaining)

Priority Issue
High i18n system unused — all Reforged UI is hardcoded English
High No focus trap or aria roles in modals
Medium Save failures are silent to the user
Medium Dead event constants and stale i18n keys for removed features

Test plan

  • Verify login with banned account returns 403 on all auth methods
  • Verify username with special characters is rejected on register/change
  • Verify game state save is rate limited after 30 rapid requests
  • Verify CSP headers are present in responses
  • Verify /api/health returns 503 when DB is down
  • Verify PvP rating changes correctly with concurrent fights
  • Verify expedition rewards are correctly distributed to all members

🤖 Generated with Claude Code

https://claude.ai/code/session_0181r4N9n3YMSMMPWbkDGSNo


Generated by Claude Code

Security:
- Enable CSP headers (was disabled) with Stripe/Google/Discord/WS allowlist
- Enforce ban check on all login paths (password, Discord, Google OAuth)
- Add rate limiter on game state save endpoint (30 req/min)
- Validate username format (alphanumeric, underscore, hyphen only)
- Use distinct JWT_SECRET and JWT_REFRESH_SECRET defaults in dev
- Validate settings payload size (max 20 keys, 200 char values)

Stability:
- Remove competing SIGINT/SIGTERM handlers from prisma.js (index.js handles shutdown)
- Clear cleanup intervals on graceful shutdown
- Export combat log cleanup interval for shutdown cleanup
- Health check now verifies database connectivity

Performance:
- Batch expedition member gold/XP updates (was N individual queries per member)
- Use atomic PvP rating increment instead of direct set (prevents concurrent race)
- Add missing database index on ChatMessage.senderId
- Add Cache-Control header on monster templates endpoint

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0181r4N9n3YMSMMPWbkDGSNo
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