Environment Variable
Configure allowed origins using theCORS_ORIGIN environment variable:
Format
- Comma-separated list of fully qualified origin URLs
- Include protocol (https:// or http://)
- No trailing slashes
- Whitespace is automatically trimmed
Production Safety
The backend rejects startup ifCORS_ORIGIN=* in production mode:
Implementation Details
Origin Parsing
The backend parsesCORS_ORIGIN on startup:
allowAllOrigins: Boolean flag for wildcard detectionallowedOriginSet: Set of specific allowed origins for O(1) lookup
CORS Validation Logic
Each request’s origin is validated against the allowed set:- No origin header: Allows request (same-origin or non-browser clients)
- Origin in allowed set: Allows request
- Wildcard enabled (dev only): Allows all origins
- Origin not allowed: Rejects with CORS error
CORS Configuration
The Express CORS middleware is configured:GET- Health checks, widget bundle, admin endpointsPOST- Chat endpointsOPTIONS- Preflight requests
Content-Type- JSON request bodiesx-api-key- Chat authenticationx-widget-api-key- Chat authentication (legacy)x-admin-api-key- Admin authentication
Configuration Examples
Development (Allow All)
* wildcard is blocked in production.
Single Domain
Multiple Domains
Subdomains
Each subdomain must be listed explicitly:Wildcard subdomains (e.g.,
https://*.example.com) are not supported. List each subdomain explicitly.Local Development with Production Backend
Testing CORS Configuration
Valid Origin
Request from allowed origin succeeds:Invalid Origin
Request from unauthorized origin fails:Access-Control-Allow-Origin header.
Preflight Request
Browsers send OPTIONS preflight for cross-origin POST:Common Issues
Deployment Domain Changed
Problem: CORS errors after deploying frontend to new domain Solution: Add new domain toCORS_ORIGIN and redeploy backend:
Missing Protocol
Problem: Origin blocked despite being inCORS_ORIGIN
Solution: Include full protocol in environment variable:
Trailing Slash
Problem: Origin blocked due to trailing slash mismatch Solution: Remove trailing slashes fromCORS_ORIGIN:
Widget Embedded in Multiple Sites
Problem: Need to embed widget on many customer domains Solution: List all customer domains or use a proxy that validates origins server-side:- Dynamic CORS validation based on database of allowed customers
- Proxy service that validates customer tokens and forwards requests
Best Practices
- Principle of least privilege: Only allow necessary domains
- Use HTTPS: Always use
https://origins in production - Audit regularly: Review allowed origins quarterly
- Test changes: Verify CORS after updating origins
- Document exceptions: Note why each origin is allowed
- Monitor errors: Watch for 401/403 responses indicating blocked origins
Related Documentation
- Security Overview - Complete security features
- API Keys - API key authentication