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:

  1. Ask the resource provider to add the header.
  2. Proxy the resource through your own server.
  3. Or disable COEP (but lose SharedArrayBuffer security).
User