How HTTP Works

Response header

< Cross-Origin-Resource-Policy: same-site

Cross-Origin-Resource-Policy

Learn how Cross-Origin-Resource-Policy (CORP) blocks no-cors cross-origin requests to protect resources from Spectre attacks and data leaks.

Reviewed 3 min readintermediate2 sourcesTry itMarkdown
Direction
Response
Category
Security
Spec
Fetch Standard
On this page

TL;DR: Cross-Origin-Resource-Policy (CORP) tells the browser which sites may embed a response through a plain no-cors load, like an <img> or classic <script> tag. same-origin blocks other origins from using it. CORP isn’t access control: the request still reaches your server. Mark public assets cross-origin so pages that enforce COEP can still embed them.

What is Cross-Origin-Resource-Policy?

CORP is a response header that the browser checks on no-cors resource loads. If the policy doesn’t allow the embedding page, the browser withholds the response data from it. By then the request has usually reached your server already. MDN explains that the protection acts on the response body.

Why CORP Exists

JavaScript can’t read an opaque no-cors response, but the browser will happily use it as an image or a script. That’s enough exposure to matter for side-channel attacks such as Spectre. CORP gives the resource owner a way to say who may use the response that way. Private resources still need real authentication on top.

Syntax

Cross-Origin-Resource-Policy: same-origin

Send exactly one value: same-origin, same-site or cross-origin. Values are case-sensitive. A comma-separated list doesn’t work as an allowlist, and duplicate headers can make the browser drop the restriction entirely. Fetch defines parsing and checks.

Value Guide

same-origin requires a matching scheme, host and port. same-site allows any origin on the same site, with one transport restriction covered below. cross-origin lets any origin pass the CORP check. It doesn’t give JavaScript CORS access to the response.

Under same-site, an HTTP page can’t use an HTTPS resource, even when both hosts share a registrable domain. Meanwhile, two HTTPS hosts like app.example.com and static.example.com are different origins but the same site.

Example

A public asset’s response headers (trimmed example):

Content-Type: image/png
Cross-Origin-Resource-Policy: cross-origin

A page enforcing COEP require-corp can load this image with a no-cors request and needs no CORS permission to do it. Add crossorigin="anonymous" to the <img> and the request switches to CORS mode, which then needs CORS permission.

Practical Deployment Pattern

Set the policy where each resource is served, so same-origin-only assets and public CDN assets each get the right value. A blanket rule is how mistakes happen: put same-origin on a public image CDN and you block every no-cors consumer on another origin, including your own application host.

Implementation

In nginx, add the directive to the asset’s location:

location /public-assets/ {
    add_header Cross-Origin-Resource-Policy "cross-origin" always;
}

This assumes your existing server already serves the files at that location. nginx documents header contexts and inheritance. Make sure no backend or middleware adds a second CORP value.

In an existing Express app, set the policy before the static handler:

const express = require('express')
app.use('/public-assets', (_req, res, next) => {
  res.set('Cross-Origin-Resource-Policy', 'cross-origin')
  next()
}, express.static('/srv/app/public-assets'))

The directory is a fixed server path that requests can’t change. express.static serves the files, and the middleware in front marks them as usable cross-origin. Keep private downloads out of this directory and give them their own authentication and policy.

CORP vs CORS

CORP: same-origin won’t block a CORS-mode fetch that passes its CORS checks. In the other direction, CORP: cross-origin won’t make a fetch response readable without Access-Control-Allow-Origin. Check which mode the request used before deciding the two headers conflict.

Common Mistakes

The most common one is reaching for CORP to stop other sites framing your pages. Ordinary iframe navigations aren’t the no-cors asset loads CORP covers. To control who can frame a document, use CSP frame-ancestors or X-Frame-Options. COEP has its own separate checks for nested documents.

CORP vs CORS: Different Problems, Different Solutions

Test in a real embedding context, not just by loading the URL directly:

<img src="https://static.example.com/public-assets/logo.png" alt="Logo">

Serve that test page from a different origin and watch the Network and Console panels. curl can confirm the server returned data and the header, but only the browser tells you whether it allowed the embed:

curl -sS -D - -o /dev/null \
  https://static.example.com/public-assets/logo.png

CORP can’t name a list of partner origins. You get three choices: same origin, same site, or anyone. If partners need JavaScript access to the data, configure CORS for that separately.

Frequently asked questions

What is Cross-Origin-Resource-Policy?

CORP restricts browser use of a response in no-cors resource loads. Its values are same-origin, same-site, and cross-origin; it does not prevent the request reaching the server.

What is the difference between CORP and CORS?

CORS governs sharing responses with cross-origin scripts. CORP restricts no-cors response use, including plain image and classic script loads, and does not override a successful CORS-mode load.

When should I use CORP?

Use a policy matching the resource consumers: same-origin for origin-restricted no-cors loads, same-site for site-restricted loads, or cross-origin for public shared assets. Authenticate private data separately.

What does same-site mean for CORP?

Two HTTPS subdomains of the same registrable domain can pass the same-site check. CORP also rejects an HTTP initiating origin loading an HTTPS response, even when the hosts are otherwise same-site.

Sources

  1. MDN Web Docs: Cross-Origin-Resource-Policydeveloper.mozilla.org
  2. Fetch Standard: CORPfetch.spec.whatwg.org

Keep going

Browse /search