Refused to load the image because it violates the following Content Security Policy directive - image

We recently started using Amazon CloudFront as CDN for images and I noticed that when I'm trying to share it via Pinterest Pin It button, there is this error in the console.
[Error] [Report Only] Refused to load the image
'https://d9hblenkye2332.cloudfront.net/image.jpg' because it violates
the following Content Security Policy directive: "default-src 'self'
*.pinterest.com *.pinimg.com *.google.com connect.facebook.net *.google-analytics.com *.facebook.com www.googleadservices.com googleads.g.doubleclick.net 'unsafe-inline' 'unsafe-eval'". Note that
'img-src' was not explicitly set, so 'default-src' is used as a
fallback.
After doing some research, it seems that this is related to Content Security (http://content-security-policy.com), but I'm not sure what has to be done, especially when there is no setting for this in the CDN. Has anyone else run into this issue?

What is your origin server ? If this is S3 bucket, you might want to take a look at the CORS policy for this. Typical causes for such problems are the CORS. The settings for CORS is not done on the CDN itself, but on the orgin server behind this (if it is S3, then in the bucket CORS policy)
Some info is here:
Enabling Cross-Origin Resource Sharing - Amazon Simple Storage Service : http://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html

Related

Cache assets from a CMS for offline PWA?

I'm writing a web media viewer for images/videos and I need to cache that media for offline use.
I have a manifest and service worker so it can be installed as a PWA, and I'm trying to cache media from a list of URLs with esentially:
let cache = await window.caches.open('pwa-assets');
for(let url of allAssetURLs) {
await cache.add(url);
}
This seems to work fine for local assets, but if those URLs are on a different domain (from a CMS/CDN) I get this CORS error.
Access to fetch at 'https://storage.googleapis.com/....appspot.com/...example.mp4' from origin 'https://127.0.0.1:4173' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Web.dev has a note that cross-domain caching is possible here, but doesn't say much about it.
The URLs I'm trying to cache are for files store in google cloud storage, for example:
https://storage.googleapis.com/....appspot.com/...example.mp4
These do work if used in <img/> or <video/> tags, so I don't think it's a CORS header issue on the CDN.
You write:
These do work if used in <img/> or <video/> tags, so I don't think it's a CORS header issue on the CDN.
Loading such subresources across origins is by default compatible with the Same-Origin Policy (SOP) and doesn't trigger CORS errors. See the relevant section of the MDN Web Docs about the SOP:
Here are some examples of resources which may be embedded cross-origin: [...]
Images displayed by <img>.
Media played by <video> and <audio>.
You write:
This seems to work fine for local assets, but if those URLs are on a different domain (from a CMS/CDN) I get this CORS error.
Invoking the add method on a Cache results in a GET request. If its argument is on a different origin, the resource in question needs to be configured for CORS or you'll get a CORS error, as you've experienced. See the note in the relevant MDN Web Docs:
Note that for opaque filtered responses [...]
we can't access to [sic] the response headers, so this check
will always fail and the font won't be cached. [...]
It is something to keep in mind if you're attempting to
cache other resources from a cross-origin domain that
doesn't support CORS, though!
You write:
The URLs I'm trying to cache are for files store in google cloud storage, for example https://storage.googleapis.com/....appspot.com/...example.mp4.
This page of the Google Storage documentation explains how to configure CORS for your bucket(s), assuming those buckets are indeed yours. Otherwise, you're out of luck and won't be able to cache those resources on the client side.

Request to Spring Boot application via Cloudfront fails inexplicably with 403 status

When I navigate to web.mysite.com, a static SPA hosted in S3, it has an iframe which has a src of mysite.com/some/path, which is a Spring Boot MVC application in Elastic Beanstalk. Both are behind Cloudfront distributions for HTTPS. This path is handled in the application with a custom resource resolver. This loads successfully, but inside the iframe content there is a script tag looking for mysite.com/some/path/thatsdifferent, handled by the same resolver.
This second request fails with a 403 and I cannot determine why. Navigating to the failing mysite.com/some/path/thatsdifferent directly in my browser or using postman succeeds with a 200 status. The server is configured to allow requests from web.mysite.com through CORS configuration (and there is no CORS-related error message) and Spring Security is configured to permitAll any requests to /some/** regardless of authentication. There is no response body or error message beyond the header x-cache: Error from cloudfront.
If I navigate to the-beanstalk-env-url.com/some/path, it loads the html and then successfully loads the content from the-beanstalk-env-url.com/some/path/thatsdifferent.
Requests to a few different but similar paths succeed. Going to a path which definitely 100% does not exists returns a 404.
The server logs show that the request is being successfully handled and Cloudfront is returning reasonable responses to the client. Looking at the Cloudfront logs simply reports a 403, without any additional information.
Almost 100% of Cloudfront 403 error articles and questions involve S3, which is not the part which is failing here.
Changing the Cloudfront distribution Allowed Methods from GET, HEAD to GET, HEAD, OPTIONS causes the requests directly to mysite.com/some/path/thatsdifferent to begin failing with invalid CORS request, this was fixed by whitelisting the Accept, Authorization, Host, Origin and Referer headers. This did not fix the underlying error.
Adjusting the logging for org.springframework.security doesn't log any extra information when a failing request occurs, my application security configuration is not what is causing the error.
After replacing Cloudfront with a load balancer on my environment in Route 53, the scenario works as expected, so the problem is definitely in Cloudfront.
The solution was to switch the Cloudfront Origin Protocol policy from HTTP Only to HTTPS Only.
I don't know why this mattered from the script file and not the html file, but I decided to test it out when I discovered that if I tried to connect to the Beanstalk environment URL via https, Chrome was warning me that the certificate being used was setup for the domain that was served by the Cloudfront distribution that was causing trouble.

About using http in Heroku server?

I am a newbie to Heroku server. I found the default connection method is https.
If I switched to http, I will received the following errors when accessing
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin *** is therefore not allowed access.
Any idea to enable http access?
The problem here appears to the same-origin policy. Seems that some of your requests are mixed between plain http and https which all modern browsers interpret as having different origins.
Without seeing additional debug information, I'm going to guess the main page is still loaded via https, but the page assets (images, javascript, css etc.) are now loaded via http.
Assuming this is correct, the first step is to ensure the main html page is loaded using the same origin (same domain, same scheme (http or https) etc.).

How do I bypass the 'ports, protocols and domains must match' CORS issue whilst in development?

I have a local site running ASP.Net MVC 3 over HTTP and HTTPS through IIS Express.
The HTTP url is http://localhost:4000 and the HTTPS is https://localhost:44301.
I'm trying to hook up the Stripe payments API but it really does not like the port, protocol and domain mismatch. I've tried using CORS to tell it to trust stripe.com but it seems that it is due to the port mismatch and I cannot figure out how to tell it to ignore that.
Adding the following header does not product any difference.
Access-Control-Allow-Origin:*
When accessing my payment page via HTTP, I get the following:
Blocked a frame with origin "https://checkout.stripe.com" from
accessing a frame with origin "http://localhost:4000". The frame
requesting access has a protocol of "https", the frame being accessed
has a protocol of "http". Protocols must match.
It gets worse when using SSL as my local SSL port is not 443.
How do I tell CORS to ignore the port mismatch whilst in development?
You can disable same origin policy while in development. Load chrome with the following argument:
--disable-web-security
https://stackoverflow.com/a/6083677/287760
Didn't the error message tell you the problem? Use HTTPs.
I still get this message my live site:
Uncaught SecurityError: Blocked a frame with origin "https://checkout.stripe.com" from accessing a frame with origin "https://getaddress.io". Protocols, domains, and ports must match.
..everything still works so I wouldn't worry about it. There's not much you can do about the domains being different.

Work-around for Cross-origin image load denied by Cross-Origin Resource Sharing policy

Trying to load images from an API for use as a texture; running into Cross-origin image load denied by Cross-Origin Resource Sharing policy.
Does anyone have this working?
jsFiddle:
http://jsfiddle.net/calvintennant/AQA97/2/
Possibly related issue: https://github.com/mrdoob/three.js/issues/687
You'll need to enable CORS support where the images are hosted. Google Cloud Storage and Amazon S3 both support this.

Resources