cross-origin headers
Guide to implementing Cross-Origin Resource Sharing (CORS) and Isolation headers (COOP, COEP, CORP) for web security.
What is CORS?
Cross-Origin Resource Sharing (CORS) uses HTTP headers to tell browsers to give a web application running at one origin, access to selected resources from a different origin.
Essential CORS Headers
Access-Control-Allow-Origin
Specifies which domains can access the resource.
# Allow specific domain (Secure)
Header always set Access-Control-Allow-Origin "https://trusted-site.com"
# Allow all domains (Insecure - Use only for public APIs)
Header always set Access-Control-Allow-Origin "*"
Access-Control-Allow-Methods
Specifies allowed HTTP methods.
Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Access-Control-Allow-Headers
Specifies allowed HTTP headers in the request.
Header always set Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With"
Cross-Origin Isolation (Advanced)
Modern browser features like SharedArrayBuffer require "Cross-Origin Isolation". This protects your site from side-channel attacks (Spectre).
To enable isolation, you must set these 3 headers:
1. Cross-Origin-Opener-Policy (COOP)
Ensures your document is isolated from other documents in the same browsing context group.
Header always set Cross-Origin-Opener-Policy "same-origin"
2. Cross-Origin-Embedder-Policy (COEP)
Prevents your document from loading any non-explicitly granted cross-origin resources.
# Require all resources to explicitly allow loading (via CORP or CORS)
Header always set Cross-Origin-Embedder-Policy "require-corp"
# Report violations only (Testing)
Header always set Cross-Origin-Embedder-Policy-Report-Only "require-corp; report-to='coep-report'"
3. Cross-Origin-Resource-Policy (CORP)
Allows a resource into the same-origin process.
# Allow only same origin
Header always set Cross-Origin-Resource-Policy "same-origin"
# Allow same site
Header always set Cross-Origin-Resource-Policy "same-site"
# Allow anywhere (CDN / Public images)
Header always set Cross-Origin-Resource-Policy "cross-origin"
Implementation Examples
Apache (.htaccess)
Secure configuration for a standard site:
<IfModule mod_headers.c>
# CORS
Header always set Access-Control-Allow-Origin "https://www.yoursite.com"
# Isolation
Header always set Cross-Origin-Opener-Policy "same-origin"
Header always set Cross-Origin-Embedder-Policy "require-corp"
Header always set Cross-Origin-Resource-Policy "same-origin"
</IfModule>
Nginx
add_header Access-Control-Allow-Origin "https://www.yoursite.com" always;
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;
PHP
header("Access-Control-Allow-Origin: https://www.yoursite.com");
header("Cross-Origin-Opener-Policy: same-origin");
header("Cross-Origin-Embedder-Policy: require-corp");
header("Cross-Origin-Resource-Policy: same-origin");
Troubleshooting
"Blocked by CORS policy" Error
Cause: The backend server is missing the Access-Control-Allow-Origin header, or it doesn't match the frontend's origin.
Solution: Add the correct header to the backend response.
Images/Scripts not loading with COEP
Cause: If you enable COEP: require-corp, all external resources (CDNs, images) MUST send a Cross-Origin-Resource-Policy: cross-origin header. If they don't, they are blocked.
Solution:
- Ask the resource provider to add the header.
- Proxy the resource through your own server.
- Or disable COEP (but lose SharedArrayBuffer security).