Cross-Origin-Resource-Policy
CORP lets a resource say who may embed it, protecting against cross-origin leaks and hotlinking. Values and how it pairs with COEP.
Last update:
Everything your server publishes is embeddable by default. Any page on the web
can point an <img>, <script>, or <video> tag at your URLs and the browser
fetches the resource straight into that page's process.
Cross-Origin-Resource-Policy (CORP) is a response header a resource sends to
say who may load it: only its own origin, only its own site, or anyone.
It is the inverse of Cross-Origin Resource Sharing (CORS): CORS lets a server opt in to other origins reading its responses, while CORP lets a resource opt out of being embedded by them.
The strictest setting keeps a resource for the origin that served it:
Cross-Origin-Resource-Policy: same-originValues and what each does
| Value | Status | Description |
|---|---|---|
same-origin | ✅ Good | Only requests from the exact same origin (scheme, host, and port) receive the resource. The default-deny choice for private assets. |
same-site | ✅ Good | Requests from the same registrable domain pass, subdomains included, with one scheme rule: an HTTP page cannot load an HTTPS resource this way. |
cross-origin | ✅ Good | Any origin may load the resource. For truly public assets only; it exists mainly so pages behind COEP require-corp can still load them. |
A missing header behaves like cross-origin: the resource stays loadable by
everyone. So does a value the browser cannot parse. Anything other than these
three keywords is treated as if no header were sent, so a typo silently turns
the protection off.
CORP does not stop the request. The browser sends it, your server answers, and only then does the browser check the header and, on a mismatch, withhold the body and fail the load with a network error. The resource never enters the embedding page's process, but the request still reached your server.
The check applies only to no-cors requests, the default mode for <img>,
<script src>, <audio>, <video>, and stylesheets loaded without a
crossorigin attribute. A request made in CORS mode skips the CORP check,
because CORS already requires an explicit grant from the server. Requests from
the resource's own origin always pass, whatever the value. And CORP does not
block top-level navigations or plain <iframe> embeds on its own; iframe
responses are CORP-checked only when the embedding document enforces COEP
require-corp.
What it protects against
- Spectre-class side channels. CORP was revived in 2018, from the older From-Origin proposal, in response to Spectre and Meltdown. Those attacks let a malicious page read any data that shares its process, including cross-origin resources it embedded. CORP keeps your resource out of the attacker's process in the first place, so there is nothing to read.
- Cross-site script inclusion (XSSI). A script marked
same-originorsame-sitecannot be pulled in by another site's<script>tag, closing off attacks that include your scripts to read the data they carry. - Hotlinking. Supporting browsers refuse to render your images and media on other sites. Note the limit: non-browser clients ignore the header, so this is embedding control, not bandwidth protection.
Browsers already enforce a default floor here. Opaque Response Blocking (ORB)
blocks no-cors reads of clearly-data responses (HTML, JSON, XML, PDFs,
archives) with no header needed, but it deliberately lets JavaScript, CSS,
images, and media through so existing sites keep working. The
ORB explainer strongly encourages protecting
those pass-through resource types with Cross-Origin-Resource-Policy when
they contain anything sensitive. Treat ORB as the default and CORP as the
explicit control for what it lets through.
The COEP connection
Cross-Origin-Embedder-Policy (COEP)
is the other half of the pair, and its own page covers it in full. A document
that enforces Cross-Origin-Embedder-Policy: require-corp only loads
cross-origin subresources that opt in, and it treats a missing or malformed
CORP header as same-origin. That flipped default is what blocks unlabeled
third-party assets, and it is why any host serving genuinely public assets (a
CDN, a widget, a font service) must send
Cross-Origin-Resource-Policy: cross-origin to stay embeddable in isolated
contexts.
One gotcha catches many rollouts: adding Access-Control-Allow-Origin to a
no-cors response does not satisfy require-corp. Either the embedding element
makes a real CORS request (a crossorigin attribute), or the resource sends
CORP. COEP's credentialless value is the alternative that loads CORP-less
cross-origin resources by stripping credentials from the request.
Risks without it
Any site can pull your assets into its own process. A page you have never
heard of can embed the avatars, charts, or documents your server returns for
logged-in users, then use a speculative-execution side channel to read them.
It can include your scripts with a <script> tag and observe what they expose
(XSSI). And it can hotlink your images and media, serving your content in its
own pages. ORB blocks only the clearly-data cases; everything else rides on
the cross-origin default until you send the header.
Risks and gotchas when using it
same-originbreaks multi-subdomain setups. Assets served fromcdn.example.comand consumed bywww.example.comare cross-origin to each other, sosame-originblocks them. Usesame-sitewhen subdomains share assets.- The HTTPS edge case in
same-site. The requester's scheme matters: an HTTP page cannot load an HTTPS resource markedsame-site, even on the same registrable domain. This is the specified and implemented behavior, even though some documentation prose omits it. - Overmarking public assets breaks consumers. Setting
same-originorsame-siteon assets other sites are meant to load breaks every third-party consumer, including any page that enforces COEPrequire-corp. Those assets needcross-origin. - Safe to deploy everywhere. Browsers without CORP support ignore the header, so shipping it carries no compatibility risk.
- It pairs well with server-side isolation. CORP is enforced by the
browser after the response arrives. Rejecting unwanted requests on the
server with Fetch Metadata
(for example, refusing
Sec-Fetch-Site: cross-site) complements it.
How to set it up
- Classify what you serve into three buckets: private assets used by one origin, assets shared across your subdomains, and public assets meant for other sites.
- Set the header per bucket:
same-originon private assets,same-siteon subdomain-shared assets,cross-originonly on the public ones. - If any of your pages will enable COEP
require-corp, load them with the new headers in place and confirm every subresource still arrives; a resource you overmarked in step 2 fails there first. - Check the deployed header, and the rest of your response headers, with the security headers scanner.
Recommendation
Send Cross-Origin-Resource-Policy: same-site as the default for your own
assets:
Cross-Origin-Resource-Policy: same-siteThe OWASP HTTP Headers cheat sheet
recommends same-site, limiting resource loading to your site and its
subdomains. Treat it as the ceiling, not the floor: prefer same-origin
wherever subdomains do not need the asset, and relax to cross-origin only on
assets other sites are meant to load, including COEP-isolated ones.
Browser support
Supported across current Chrome, Edge, Firefox, and Safari. Browsers without support ignore the header, so there is no downside to sending it everywhere.
FAQ
What is the difference between CORP and CORS?
They are inverses. CORS is opt-in: a resource uses it to let other origins read its content. CORP is opt-out: a resource uses it to declare who may embed it cross-origin. CORP only governs no-cors requests, the default mode of images, scripts, and media, while CORS-mode requests skip the CORP check entirely.
What is the difference between CORP and COEP?
CORP is set by the resource and says who may load it. COEP is set by the
embedding page and says it will only load resources that opt in. A missing CORP
header is treated as same-origin under COEP require-corp, which is what
blocks unlabeled third-party assets. See
CORP vs COEP for the full comparison.
Does CORP block hotlinking?
In browsers, yes. A cross-origin no-cors load of a resource marked
same-origin or same-site fails with a network error, so another site cannot
embed your image or script. Non-browser clients ignore the header, though, so
treat CORP as embedding control against browsers, not as bandwidth or theft
protection.
See also
- Security headers overview
- Cross-Origin-Embedder-Policy (COEP), the page-side policy that makes CORP opt-in mandatory
- Cross-Origin-Opener-Policy (COOP), the other half of cross-origin isolation
- Security headers scanner to check your deployed headers