Cross-Origin-Resource-Policy security response
Restricts which origins can load this resource — a defence against cross-origin information leaks and Spectre-style attacks.
What it does
Cross-Origin-Resource-Policy (CORP) tells the browser which origins are allowed to load this resource. A page from evil.com trying to embed an image from yourapi.com with CORP: same-origin will be blocked — the browser refuses to load the resource for that cross-origin request.
This is distinct from CORS (which governs JavaScript's ability to read cross-origin responses). CORP governs whether the browser will even load the resource at all — including via <img>, <script>, <video>, and CSS background images where CORS doesn't apply.
Syntax
Cross-Origin-Resource-Policy: same-origin
Cross-Origin-Resource-Policy: same-site
Cross-Origin-Resource-Policy: cross-origin
Values
same-origin
Only pages from the exact same origin (scheme + host + port) can load this resource.
Cross-Origin-Resource-Policy: same-origin
https://app.example.com can load it. https://other.com cannot. Even https://sub.example.com cannot (different host).
same-site
Pages from the same site can load this resource. "Same site" means same registrable domain (eTLD+1), regardless of subdomain or scheme (with some nuance).
Cross-Origin-Resource-Policy: same-site
https://app.example.com can load it. https://api.example.com can load it. https://other.com cannot.
cross-origin
Any origin can load this resource. This is the permissive option — equivalent to no restriction, but explicitly declared.
Cross-Origin-Resource-Policy: cross-origin
Use for public resources (fonts, images, scripts) intended for cross-origin use.
Why this exists: Spectre and side-channel attacks
CORP was designed specifically in response to Spectre (the CPU speculative execution vulnerability disclosed in 2018). Spectre allows JavaScript running in a browser tab to read memory from the same process. If a cross-origin resource (say, an authenticated API response or a user avatar) is loaded into your process's memory — even if JavaScript can't read the response due to CORS — Spectre-style attacks might be able to infer its contents from timing side-channels.
By setting CORP: same-origin or same-site, the resource is never loaded into a cross-origin page's memory at all — Spectre can't leak what isn't there.
The CORP + COEP relationship
Cross-Origin-Embedder-Policy: require-corp (COEP) requires that all cross-origin resources loaded by a page either have CORP: cross-origin (explicitly opt in to cross-origin loading) or use CORS. This is necessary to enable SharedArrayBuffer and high-resolution performance.now() — APIs restricted post-Spectre.
The dance:
- Your page sets
COEP: require-corp - Every cross-origin resource your page loads must set
CORP: cross-origin(or have CORS) - If any resource doesn't cooperate, it's blocked and your page can't load it
This is why CDN-hosted fonts, analytics scripts, and external images all needed updates after Spectre.
When to set CORP
On internal/authenticated resources: APIs returning user-specific data, authenticated image endpoints, private file downloads — set same-origin or same-site. There's no reason for evil.com to be able to embed your users' profile pictures.
On public CDN resources: If you want your CDN assets usable by third parties (open source fonts, public images), set cross-origin. If you want COEP-enabled pages to load your resources, they need cross-origin (or CORS).
On API responses: JSON API responses aren't typically embeddable via <img> or <script>, so CORP is less critical there — CORS handles JavaScript access. But setting same-origin is a good defensive habit.
Common mistakes and gotchas
Not setting CORP and then enabling COEP. If you add COEP: require-corp to your page without updating your own resources to serve CORP: cross-origin, your own assets will start failing to load. Always audit and update your resources before enabling COEP.
Confusing CORP with CORS. CORS governs JavaScript's ability to read cross-origin responses. CORP governs whether the browser loads the resource at all. They're complementary but distinct. A resource with Access-Control-Allow-Origin: * (CORS) but no CORP can still be restricted by CORP: same-origin — CORS doesn't override CORP.
Using same-site without understanding its scope. same-site allows all subdomains. If a subdomain is compromised or user-controlled (user-uploads.example.com), it can load your same-site restricted resources. Prefer same-origin for sensitive resources.
Real-world examples
Private user avatar API:
HTTP/1.1 200 OK
Content-Type: image/jpeg
Cross-Origin-Resource-Policy: same-origin
Cache-Control: private, max-age=3600
Public CDN font (supporting COEP-enabled pages):
HTTP/1.1 200 OK
Content-Type: font/woff2
Cross-Origin-Resource-Policy: cross-origin
Access-Control-Allow-Origin: *
Cache-Control: public, max-age=31536000
Internal API resource:
HTTP/1.1 200 OK
Content-Type: application/json
Cross-Origin-Resource-Policy: same-site
FAQ
Is CORP needed if I already have CORS?
They serve different purposes. CORS restricts JavaScript's ability to read cross-origin responses. CORP restricts whether the browser loads the resource at all — including no-CORS loads from <img>, <script>, CSS, etc. For sensitive resources, set both.
Does CORP affect <link rel="preload">?
Yes. preload requests are also subject to CORP. If a resource has CORP: same-origin and you try to preload it from a cross-origin page, it'll be blocked.
What's the default if CORP isn't set?
Resources without CORP can be loaded from any origin by default — the status quo pre-Spectre. For public assets, this is fine. For sensitive resources, the absence of CORP is a potential information leak vector.
Fun fact
Cross-Origin-Resource-Policy, along with Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy, is part of a trio of headers that emerged directly from the Spectre and Meltdown CPU vulnerability disclosures in January 2018. Before Spectre, browser security assumed process isolation was sufficient. Spectre showed it wasn't — JavaScript in one tab could potentially read another tab's memory. The browser response was to introduce these headers to opt resources and pages into stricter isolation, trading some cross-origin capability for protection against an entirely new class of hardware-level attacks.