Skip to content

Security, performance, and stability quick wins - #177

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

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

Conversation

@Sparksx

@Sparksx Sparksx commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Summary

Comprehensive audit of the Gear Master codebase across security, performance, stability, and functionality — followed by implementation of all high-priority quick wins (low effort, high impact).

Security fixes

  • Ban enforcement on HTTP API routes (critical) — banned users were only blocked from Socket.io connections, not REST endpoints. They could still save game state, buy gold, operate in clans, and fight PvP. Added a banGuard middleware to all gameplay routes.
  • Content Security Policy enabled — helmet was configured with contentSecurityPolicy: false, removing all browser-level XSS protection. Now sets a functional CSP allowing self, Stripe, Google, Discord, and necessary inline styles.
  • Stripe redirect URL hardenedsuccess_url/cancel_url were built from client-supplied Origin/Referer headers (phishing risk). Now uses server-configured CORS_ORIGIN.
  • Rate limiting on /refresh — was missing the authLimiter applied to all other auth endpoints.
  • Settings key whitelistPUT /api/auth/settings accepted arbitrary JSON keys. Now only allows known keys (theme, language, sfx, music, notifications).
  • Distinct JWT dev secretsJWT_SECRET and JWT_REFRESH_SECRET shared the same fallback value in development, enabling token confusion.

Performance fixes

  • Lightweight clan listing queryGET /api/clans was loading full member equipment JSON (hundreds of KB) for all 25 clans when only memberCount is needed for the list view.
  • Cache-Control headers on monster templates, sprites, and payment packs (static data, 1h TTL).
  • Static asset cachingexpress.static now sets maxAge: '1d' + etag: true in production.
  • Parallelized socket middleware — ban check + role fetch now use Promise.all instead of sequential queries.

Stability fixes

  • Interval cleanup on shutdownsetInterval handles for token cleanup (24h) and combat log cleanup (1h) are now stored and cleared during graceful shutdown.
  • Removed duplicate Prisma shutdown handlers that could race with the main shutdown() function and bypass io.close()/server.close().

Test plan

  • All 524 tests pass (npm test)
  • Linter passes with zero errors (npm run lint)
  • Production build succeeds (npm run build)
  • Verify banned user receives 403 on game/clan/pvp/payment API calls
  • Verify CSP headers present in production response
  • Verify Stripe checkout redirects to configured origin, not spoofed header
  • Verify clan listing response size is significantly smaller

🤖 Generated with Claude Code

https://claude.ai/code/session_019E8KUzJGkSxnfmeDY8KPG8


Generated by Claude Code

Security:
- Add ban enforcement on HTTP API routes (banned users were only blocked
  from Socket.io, not REST endpoints) — critical fix
- Enable Content Security Policy via helmet (was fully disabled)
- Fix Stripe checkout redirect URLs: use server-configured CORS_ORIGIN
  instead of client-supplied Origin/Referer headers (anti-phishing)
- Add rate limiting to the /refresh endpoint (was missing authLimiter)
- Whitelist allowed keys in PUT /api/auth/settings to prevent arbitrary
  JSON storage
- Use distinct JWT_SECRET and JWT_REFRESH_SECRET dev fallback values to
  prevent token confusion in development

Performance:
- Use lightweight include for clan listing (skip full member equipment
  JSON — was loading hundreds of KB of gear data for 25 clans)
- Add Cache-Control headers to monster templates, sprites, and payment
  packs endpoints (static data, 1h TTL)
- Add maxAge + etag to express.static for production asset caching
- Parallelize socket ban check + role fetch (Promise.all instead of
  sequential queries, halving connection latency)

Stability:
- Store and clear setInterval handles (token cleanup, combat log cleanup)
  during graceful shutdown to prevent process hang
- Remove duplicate Prisma SIGINT/SIGTERM handlers that could race with
  the main shutdown handler and bypass io.close()/server.close()

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