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-originThe 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-originsame-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-origina 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.comThey 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-originFor infrastructure deliberately shared among same-site origins, same-site can express that architecture:
Cross-Origin-Resource-Policy: same-siteThe 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.comConversely, 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-corpand a public cross-origin asset intended for that document might return:
Cross-Origin-Resource-Policy: cross-originThe 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 assetsThe 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 failFor 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.