Cross-Origin-Resource-Policy Controls no-cors Embedding

Web pages routinely embed resources without granting JavaScript direct access to their response bytes. Images, classic scripts, media, and other subresources can use no-cors request mode, where the browser permits forms of cross-origin loading while keeping the response opaque to script.

That default is useful for the web, but a resource owner may need a tighter boundary. Cross-Origin-Resource-Policy (CORP) is an HTTP response header that tells the browser which origins or sites may consume a response through the policy’s no-cors path.

A restrictive response can carry:

Cross-Origin-Resource-Policy: same-origin

The header does not turn a private endpoint into a public one, grant CORS access, or replace server-side authorization. It is a browser-enforced response policy for a specific class of resource loads.

CORP is attached to the resource

The server that returns a resource sets CORP on that resource’s response. This makes the policy different from a document-level rule that lists destinations a page may contact.

The defined values are:

Cross-Origin-Resource-Policy: same-origin
Cross-Origin-Resource-Policy: same-site
Cross-Origin-Resource-Policy: cross-origin

same-origin permits the relevant consumption when the request origin and resource origin are the same. Origin comparison includes scheme, host, and port.

same-site permits a broader relationship based on the browser’s same-site rules. Separate origins can therefore qualify as same-site. That distinction matters for deployments that split applications and static assets across related hosts.

cross-origin permits cross-origin consumption for this policy. It is useful for resources intentionally published for broad embedding, including resources that must remain available to documents enforcing an embedder policy.

Choosing among these values is a statement about the resource’s intended embedding boundary, not a ranking to apply mechanically to every response.

The policy acts on no-cors responses

CORP is relevant to requests that use no-cors mode. A common example is an image embedded without a CORS opt-in:

<img src="https://media.example.net/account-badge.png" alt="">

If the response from media.example.net declares:

Cross-Origin-Resource-Policy: same-origin

a document from a different origin cannot consume that response through the applicable no-cors path. The browser performs the CORP check and blocks the response from being delivered for that use.

The network request itself may already have reached the server. CORP must not be treated as a mechanism that guarantees no request is sent. Server-side access control remains responsible for deciding whether a requester is entitled to sensitive data.

This distinction also affects logging and incident analysis. A server can observe a request even when the browser later refuses to expose the response to the embedding context.

same-site is broader than same-origin

Consider these origins:

https://app.example.com
https://static.example.com

They are different origins because their hosts differ. Depending on the applicable site calculation, they can still be same-site.

A resource intended only for app.example.com should not use same-site merely because both hosts belong to one organization. If another same-site origin is less trusted, the broader policy can admit a relationship the resource owner did not intend.

For a resource whose valid consumers are strictly same-origin, the narrower declaration is direct:

Cross-Origin-Resource-Policy: same-origin

For infrastructure deliberately shared among same-site origins, same-site can express that architecture:

Cross-Origin-Resource-Policy: same-site

The correct value follows the actual trust boundary.

CORP and CORS solve different problems

CORS controls whether browser code can make certain cross-origin requests and access their responses. CORP lets the resource response restrict applicable no-cors consumption.

An API designed for JavaScript access from another origin generally needs an appropriate CORS policy. Adding CORP does not substitute for headers such as:

Access-Control-Allow-Origin: https://app.example.com

Conversely, a resource that is embedded through a no-cors path can be affected by CORP even though application code never receives a normal readable CORS response.

Keeping these mechanisms separate avoids a common configuration error: treating every cross-origin header as another spelling of the same permission.

CORP participates in COEP enforcement

Cross-Origin-Embedder-Policy: require-corp changes the embedding rules for a document. Under that policy, cross-origin resources requested in no-cors mode need to satisfy the applicable CORP requirement, while resources requested in CORS mode are governed by CORS.

A document might return:

Cross-Origin-Embedder-Policy: require-corp

and a public cross-origin asset intended for that document might return:

Cross-Origin-Resource-Policy: cross-origin

The two headers express policy from different sides. COEP is attached to the embedding document; CORP is attached to the resource. A resource can therefore state that cross-origin no-cors consumption is acceptable rather than relying on the embedder to assume consent.

CORP is also relevant outside a COEP deployment. A resource can send a restrictive CORP value on its own.

Apply the header according to resource class

A single site can contain resources with very different exposure requirements. Public logos, authenticated account images, downloadable reports, application scripts, and shared CDN assets do not necessarily belong behind one CORP value.

A practical deployment starts by classifying resource routes:

/account/*       -> private or same-origin use
/static/app/*    -> application-controlled assets
/public/media/*  -> intentionally embeddable assets

The mapping is application-specific. The important property is that the header follows the intended consumer set rather than the convenience of one global middleware rule.

Caching also deserves attention. If an intermediary can cache responses that differ in authorization or content, CORP does not repair an unsafe cache key. Authentication, authorization, cache controls, and CORP remain separate layers.

Validate behavior at the browser boundary

Header presence alone is not sufficient evidence that a deployment matches its design. Tests should exercise the resource from origins that represent the intended and rejected relationships.

For a same-origin resource, useful cases include:

same origin      -> expected to pass the CORP boundary
same site        -> expected to fail if origin differs
cross site       -> expected to fail

For a deliberately public resource carrying cross-origin, the test should confirm that cross-origin embedding still works in the intended request mode.

Browser developer tools can show blocked resource loads and response headers, while server logs can confirm that a request reached the origin. Seeing both sides helps distinguish network delivery from browser consumption.

CORP is most precise when treated as resource metadata with a narrow job: declare the permitted boundary for applicable no-cors response use. Authorization still protects data at the server, CORS still governs readable cross-origin API access, and COEP still defines the embedding document’s requirements.