6.6 KiB
CORS Security Decision
Overview
The backend service includes game content routes that intentionally use
Access-Control-Allow-Origin: * (wildcard) to allow cross-origin requests from
any origin. This document explains the security rationale and justification for
this decision.
Location
- Backend Files:
backend/src/game/legacy-server.ts,backend/src/game/gamezipserver.ts - Routes:
/game-proxy/*- HTTP proxy for game content/game-zip/*- ZIP file streaming
Security Decision
Decision: Allow all origins (*) for backend game content routes
Rationale:
1. Public Game Content
The backend game content routes serve public, read-only game content from the Flashpoint Archive:
- Flash game files (.swf)
- HTML5 game files (.html, .js, .css)
- Game assets (images, audio, etc.)
- Animation files
All content served is:
- ✅ Public domain or freely redistributable
- ✅ Read-only (no data modification)
- ✅ Non-sensitive (no user data, credentials, or private information)
- ✅ Cacheable and intended for broad distribution
2. Game Embedding Use Cases
The wildcard CORS policy supports legitimate use cases:
- Embedding Flash/HTML5 games in iframes across different domains
- Running games from
http://localhost:3100/game-proxy/*while frontend is onhttp://localhost:5173 - Supporting different development environments and ports
- Allowing community-hosted instances with various domain configurations
3. No Sensitive Data Exposure
The backend game content routes do NOT serve:
- ❌ User data or personal information
- ❌ Authentication tokens or credentials
- ❌ Private database records
- ❌ Configuration secrets
- ❌ API keys or sensitive settings
All sensitive operations are handled by the backend service (port 3100) which has restrictive CORS configured to only allow the specific frontend origin.
4. Security Boundaries
Backend API Routes (/api/*) - Restricted CORS:
// backend/src/server.ts
cors({
origin: (origin, callback) => {
// Checks env var and dynamic domains table
// Allows only configured origins
},
credentials: true,
});
- Handles authentication
- Manages user data
- Enforces RBAC permissions
- Uses restrictive CORS with credentials
Backend Game Content Routes (/game-proxy/*, /game-zip/*) - Permissive CORS:
// backend/src/game/cors-handler.ts
res.setHeader('Access-Control-Allow-Origin', '*');
- Serves public game files only
- No authentication required
- No sensitive data access
- Read-only content delivery
5. Additional Security Measures
Even with wildcard CORS, the backend game content routes implement:
-
Path Traversal Prevention
- Centralized security utilities in
backend/src/game/utils/pathSecurity.ts - Validates ZIP mount IDs and file paths
- Blocks
..,/,\, null bytes, and URL-encoded traversal - Restricts ZIP files to allowed games directory
- Comprehensive test coverage (17 test cases)
- Centralized security utilities in
-
Request Size Limits
- 1MB maximum request body size
- Prevents DoS attacks
-
Read-Only Operations
- No write, update, or delete operations
- ZIP mounting is internal only
- File serving is GET-only
-
No Credential Sharing
- No cookies or authentication headers
- No
Access-Control-Allow-Credentials - Stateless file serving
Separation of Concerns
The wildcard CORS policy for game content routes is separate from the backend API CORS configuration:
- Backend API (
/api/*): Restrictive CORS, only allows configured origins - Game Content (
/game-proxy/*,/game-zip/*): Permissive CORS, allows all origins
Both routes run on the same backend service (port 3100) but are isolated by path.
Alternatives Considered
Alternative 1: Whitelist Frontend Origin Only
Rejected: Would break game embedding and require reconfiguration for every deployment environment.
Alternative 2: Dynamic Origin Validation
Rejected: Adds complexity with no security benefit given the public, read-only nature of served content.
Alternative 3: Separate Backend Service
Previously Implemented: Before the game-service merger, the game service ran on separate ports (22500/22501). Now integrated into the backend with separate route prefixes.
Risk Assessment
Risk Level: ✅ LOW
Justification:
- Content is public and intended for broad distribution
- No sensitive data exposure
- No write operations
- Backend handles all authentication/authorization with restrictive CORS
- Additional security measures prevent abuse
Monitoring and Compliance
Monitoring:
- Request logs track file access patterns
- Unusual access patterns can be detected via backend activity logging
- ZIP mount operations are logged for audit
Compliance:
- Meets OWASP security guidelines for public content delivery
- Follows principle of least privilege (game-service has no database access)
- Implements defense in depth (multiple security layers)
Backend API Dynamic CORS (Updated 2026-02)
The backend API routes now support dynamic CORS in addition to the static
DOMAIN environment variable:
Implementation: backend/src/server.ts
origin: (origin, callback) => {
if (!origin) return callback(null, true); // same-origin
if (origin === config.domain) return callback(null, true); // env var
// Check domains table (cached 60s)
const allowed = domainService.getAllowedOrigins();
if (allowed.has(origin)) return callback(null, true);
callback(new Error('Not allowed by CORS'));
};
How it works:
- Admins configure domains via
/api/domainsendpoints DomainService.getAllowedOrigins()generates bothhttp://andhttps://variants per hostname- Results cached in-memory for 60 seconds, invalidated on any domain mutation
- Falls back to
DOMAINenv var if no domains configured or DB unavailable
Game Content Routes: Game content routes (/game-proxy/*, /game-zip/*)
always use wildcard CORS (*) for public game embedding, regardless of domain
configuration.
Conclusion
The wildcard CORS policy for backend game content routes is a justified security decision that:
- Serves only public, read-only game content
- Exposes no sensitive data
- Supports legitimate embedding and development use cases
- Maintains strong security boundaries with the backend service
- Implements additional security measures to prevent abuse
This decision has been reviewed and documented for security audit purposes.
Last Updated: 2026-01-27 Reviewed By: Code Review Process Status: Approved - Justified for public content delivery