httpcontent-security-policycross-origin-embedder-policycross-origin-resource-policycross-origin-opener-policy

CORP Blocking an Obviously Same-Origin Request with CSP sandbox Set


Imagine a site with two documents: index.html and test.jpg, both located at the root. index.html has the following content.

<!DOCTYPE html>
<html lang=en>
        <head>
                <meta charset=utf-8>
                <meta content="text/html; charset=utf-8" http-equiv=content-type>
                <title>Test</title>
        </head>
        <body>
                <p>Hello.</p>
                <img src="/test.jpg">
        </body>
</html>

If served with no security headers, this works just fine. However, with these headers on index.html:

Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin

and this header on test.jpg:

Cross-Origin-Resource-Policy: same-origin

test.jpg will no longer be loaded by Chrome 98. It reports net::ERR_BLOCKED_BY_RESPONSE.NotSameOrigin 200 in the console.

Adding the following header to index.html will cause the image to be blocked by Firefox 97 as well:

Content-Security-Policy: default-src 'none'; style-src 'self'; img-src 'self'; prefetch-src 'self'; frame-ancestors 'none'; form-action 'none'; upgrade-insecure-requests; block-all-mixed-content; disown-opener; sandbox; base-uri 'none'

(I'm aware that that's a lot of directives, but I tried to bisect them to what was important and couldn't figure it out.)

What is happening here? https://example.com and https://example.com/test.jpg are the same origin, aren't they? Explicitly navigating to https://example.com/index.html also blocks the loading of test.jpg. What is missing from my understanding of same-origin? Why is there a difference between Chrome and Firefox's handling? Why does adding CSP cause Firefox to start blocking the requests for test.jpg?

In case I missed something, here are the complete set of headers for each request (from cURL):

> GET / HTTP/2
> Host: example.com
> user-agent: curl/7.77.0
> accept: */*
>
< HTTP/2 200
< date: Wed, 16 Feb 2022 04:56:43 GMT
< server: Apache
< via: e3s
< last-modified: Wed, 16 Feb 2022 04:43:18 GMT
< content-length: 226
< x-content-type-options: nosniff
< referrer-policy: same-origin
< content-security-policy: default-src 'none'; style-src 'self'; img-src 'self'; prefetch-src 'self'; frame-ancestors 'none'; form-action 'none'; upgrade-insecure-requests; block-all-mixed-content; disown-opener; sandbox; base-uri 'none'
< cross-origin-embedder-policy: require-corp
< cross-origin-opener-policy: same-origin
< etag: "e2-5d81b49ddfad8"
< accept-ranges: bytes
< vary: Accept-Encoding
< content-type: text/html; charset=UTF-8
<
> GET /test.jpg HTTP/2
> Host: example.com
> user-agent: curl/7.77.0
> accept: */*
>
< HTTP/2 200
< date: Wed, 16 Feb 2022 04:52:19 GMT
< server: Apache
< x-content-type-options: nosniff
< referrer-policy: same-origin
< cross-origin-resource-policy: same-origin
< last-modified: Wed, 16 Feb 2022 04:22:59 GMT
< etag: "18692-5d81b013bbe82"
< accept-ranges: bytes
< content-length: 99986
< cache-control: public, max-age=31557600, immutable
< age: 336
< via: e2s
< content-type: image/jpeg
<

Solution

  • I have not tried to reproduce, but from reading this it would make sense for Firefox to start blocking as you sandboxed the document, meaning it has an opaque origin and therefore the image will appear cross-origin.

    As for Chrome, could sandboxing have been in effect there too somehow?