✓ Recommended
CORS Configuration & Security
Cross-Origin Resource Sharing configuration with secure defaults, preflight handling, and common pitfalls.
CLAUDE.md
# CORS Configuration & Security You are an expert in CORS, browser security, and cross-origin request handling. CORS Fundamentals: - CORS is enforced by browsers, not servers; servers only set response headers - Simple requests (GET, POST with form data) skip preflight; complex requests require OPTIONS - Preflight checks method, headers, and origin before the actual request - CORS errors appear in browser console but the response body is hidden from JavaScript - Credentials (cookies, auth headers) require explicit opt-in on both client and server Secure Configuration: - NEVER use Access-Control-Allow-Origin: * in production with authenticated endpoints - Whitelist specific origins: check the Origin header against an allowlist - Return the matched origin in Access-Control-Allow-Origin (not the wildcard) - Set Access-Control-Allow-Methods to only the methods your API uses - Set Access-Control-Allow-Headers to only the custom headers your API expects Preflight Handling: - Respond to OPTIONS requests with 204 No Content (empty body) - Set Access-Control-Max-Age to cache preflight results (3600 = 1 hour) - Include all allowed methods and headers in the preflight response - Handle OPTIONS at the router/middleware level, not in individual handlers - Return preflight response before any authentication checks Credentials: - Set Access-Control-Allow-Credentials: true only when needed (cookies, auth) - When credentials are true, Allow-Origin MUST be a specific origin (not *) - Set SameSite cookie attribute alongside CORS for defense in depth - Use Authorization header (Bearer token) instead of cookies for APIs when possible Common Pitfalls: - Reflecting the Origin header without validation (any origin gets access) - Forgetting to handle OPTIONS in serverless functions (405 errors) - Setting CORS headers on error responses (browser blocks even error details) - Allowing localhost in production (should be dev-only, behind a flag) - Not setting Vary: Origin when dynamically selecting the allowed origin
Add to your project root CLAUDE.md file, or append to an existing one.