Django admin Resource Policy COEP ERR_BLOCKED_BY_RESPONSE - django

The static files of my Django admin site are on a S3 bucket (DigitalOcean Spaces actually) and in the Console I get a ERR_BLOCKED_BY_RESPONSE.NotSameOriginAfterDefaultedToSameOriginByCoep 200
In the network panel all the static files are considered 3rd party and blocked for this reason (not same origin)
The response to any one of these files contains a not set cross-origin-resource-policy error which says:
To use this resource from a different origin, the server needs to specify a cross-origin resource policy in the response headers.
What I tried :
Following the error message, I tried to set a response header on the ressources, something like Cross-Origin-Resource-Policy: cross-origin. But in a DigitalOcean Spaces I cannot set headers other than Content-Type, Cache-Control, Content-Encoding, Content-Disposition and custom x-amz-meta- headers.
I tried to extend the Django admin/base.html template, duplicate a few link tags and manually set a crossorigin attribute to them. This way the resources are queried twice, one query is blocked as before and the other one is working. The only difference in the headers is that the Origin is set. Is there a way to tell Django to add a crossorigin attribute to all link and script and img tags of the Django admin templates ?
I tried to remove the Cross-Origin-Opener-Policy and Cross-Origin-Embeder-Policy headers on the ingress loadbalancer, which I guess cause the blocking, by setting them to unsafe-none. Even though I think it should work with the policy, the change had no effect on the problem which I don't understand.
What I didn't try:
I found this tutorial explaining how to set custom headers on S3 Responses. The idea is to have a Lambda function in front modifying a x-amz- header to a standard header. Not sure I can easily replicate this with DigitalOcean Functions.
My workaround:
The ugly hack is to duplicate all Django admin templates and manually add a crossorigin attribute where needed.
I don't know where this comes from, a few weeks ago it was all good. Any help appreciated.

With HTTP 2+ it's more efficient to serve assets from the same domain, as they can be served on a single connection. Most sites should be doing this. Whitenoise is a popular solution for doing so with minimal configuration: ​https://whitenoise.evans.io/en/stable/
This solves the problem.
Thanks to Adam Johnson from djangoproject.

Related

Static content on CloudFront is cached incorrectly over time

I have set up a CloudFront on top of multiple S3 buckets (in different regions) to provide a fast stable version of my webapp. This webapp is implemented with React which means it's all one single HTML file and one single Javascript file.
Using the routing mechanism of React, all the paths in the URL are handled within the code. This means if I click on a link like www.example.com/users, there won't be a request sent to the server. Instead, the client code will render the appropriate page without any consultation with the server (I'm just talking about the HTML and not considering the data). This means that if some user types in the given URL, the server should return the index.html (the only HTML file I have) which then will take care of the URL on the client-side. In other words, all the requests sent to the server should either return the HTML file or the Javascript file I mentioned earlier. Even the requests that are pointing to none-existing files.
In order to implement this requirement, I asked this question and I got an answer like this:
I need to set up an error page for my distribution on CloudFront and
redirect all the 403 (Forbidden) requests to /index.html file. This
is because when the request is pointing to a nonexisting file on S3,
S3 will return 403 to CloudFront due to the lack of listing
permission. Or I can grant the listing permission and instead handle
the 404 error (I didn't test this latter option).
Anyways, I set this up and it works perfectly - for a few hours. But then, for some unknown reason, the request to the Javascript file also returns the HTML file. And of course, all I'm getting back is actually coming from CloudFront's cache which means, no matter how many times I send the request, it will keep returning the same value. That is until I invalidate the cache on CloudFront which will solve the problem for few more hours. And we go around and around.
Even though I'm not sure why this happens but my guess is that at some point the S3 buck is inaccessible to CloudFront which will result in CloudFront caching the index.html. What can I do about this?
I think I found the problem:
MAKE SURE YOUR STATIC CONTENT ON ALL THE S3 BUCKETS ARE IDENTICAL!!!
In my case, the Javascript filename is automatically generated by Webpack which means it's random. And since different regions were "compiled" separated, their filenames differed.

Cross-Origin Read Blocking (CORB) issue when making img request

I am currently trying to implement this solution here. The solution seems pretty simple and possible since I am the owner of both of the hosts. On mysite1.com I have added the following img tag.
<img src="//mysite1.com.com/cookie_set/" style="display:none;">
On my site2.com (django), I have a view like so:
def cookie_set(request):
response = HttpResponse()
response.set_cookie('my_cookie', value='awesome')
return response
When I release this code live. I get the following error:
Cross-Origin Read Blocking (CORB) blocked cross-origin response https://www.mysite2.com/cookie_set/ with MIME type text/html. See https://www.chromestatus.com/feature/121212121221 for more details.
I thought that maybe if I just added "Access-Control-Allow-Origin" in my view this might fix things, but according the docs here: https://www.chromium.org/Home/chromium-security/corb-for-developers, there's one more consideration:
For example, it will block a cross-origin text/html response requested from a or tag, replacing it with an empty response instead.
Are my assumptions correct? After adding the correct headers should I just change the content-type to something other than text/html?
Ultimately, my final goal is I would like to set a cookie for a different domain that I have control of (ideally without a redirect).
Best solution: use a different tag for this. (i.e. iframe).
The point behind CORB is to prevent certain tags from being used for XSSI data injection So img tags requests should not return text/html, application/json, or xml content types.
So unless the call to img tag really is for capturing the request itself (for referrer tracking, for example), then you get much more versatility by executing in an iframe anyway (like for SSO-redirection workflows).
See also: Setting third party cookie by using 1x1 <img> tag - Javascript doesn't drop cookie
I fixed this for image files by updating the Content-Type metadata under Properties in S3 - image/jpeg for JPEG files and image/png for PNG files.
My application uploads image files via multer-s3 and it seems it applies Content-Type: 'application/x-www-form-urlencoded'. It has a contentType option with content-type auto-detect feature - this should prevent improper headers and fix the CORB issue.
It seems the latest Chrome 76 version update includes listening to remote file URL headers, specifically Content-Type. CORB was not an issue for other browsers such as Firefox, Safari, and in-app browsers e.g. Instagram.

AWS S3 Redirect only works on bucket as a subdomain not bucket as a directory

Many people have received 100s of links to PoCs that are on an internal facing bucket and the links are in this structure.
https://s3.amazonaws.com/bucket_name/
I added a redirect using AWS's Static website hosting section in Properties and it ONLY redirects when the domain is formatted like this:
https://bucket_name.s3-website-us-east-1.amazonaws.com
Is this a bug with S3?
For now, how do I make it redirect using both types of links? My current workaround is to add a meta redirect tag in each html file.
The s3-website is the only endpoint that supports redirects unfortunately. Using the s3.amazonaws.com supposes that you will be using S3 as a storage layer, instead of a website. If the link is to a specific object, you can place an HTML file at that url with a JS redirect, but other than that there is really no way to achieve what you are trying to do.
In the future, i would recommend always setting up a Cloudfront distribution for those kinds of usecases, as that will allow you to change the origin later on.

GET request 200 OK but 'failed to load response data' for links

I made a personal website (http://www.soyoungpark.online) using domain bought from GoDaddy and hosted on AWS s3. I set up everything and thought things were working until I put a simple link to my linkedin profile. When I check the network panel, I see that status code is 200 OK but for the response..there is nothing. The code itself doesn't seem to be problematic; it is simple a with href of the desired link. So I am guessing something could be wrong with my AWS s3 settings? Anyone with similar experience?
It's likely that these services include a header option called "X-Frame" that for security prevents them from being loaded within another site:
The X-Frame-Options HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a <frame>, <iframe> or <object> . Sites can use this to avoid clickjacking attacks, by ensuring that their content is not embedded into other sites. Source: X-Frame-Options
This does look to be the case when attempting to view Linkedin per your example:
Refused to display 'https://www.linkedin.com/in/exampleuser' in a frame because it set 'X-Frame-Options' to 'sameorigin'.
That said, applying a target Attribute to each to open in a new tab or window should allow these outside services to be navigated to.
e.g:
<a href="https://www.linkedin.com/in/exampleuser" target="_blank">

Is it possible to set Content-Security-Policy headers in Amazon S3?

I'm trying to set a Content-Security-Policy header for an html file I'm serving via s3/cloudfront. I'm using the web-based AWS console. Whenever I try to add the header:
it doesn't seem to respect it. What can I do to make sure this header is served?
I'm having the same problem (using S3/CloudFront) and it appears there is currently no way to set this up easily.
S3 has a whitelist of the headers permitted, and Content-Security-Policy is not on it. Whilst it is true you can use the prefixed x-amz-meta-Content-Security-Policy, this is unhelpful as there is no browser support for it.
There are two options I can see.
1) you can serve the html content from a webserver on an EC2 instance and set that up as another CloudFront origin. Not really a great solution.
2) include the CSP as a meta tag within your html document:
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="default-src http://*.foobar.com 'self'">
...
This option is not as widely supported by browsers, but it appears to work with both Webkit and Firefox, so the current Chrome, Firefox, Safari (and IOS 7 Safari) seem to support it.
I chose 2 as it was the simpler/cheaper/faster solution and I hope AWS will add the CSP header in the future.
S3/CloudFront takes any headers that the origin set and forward those to the client, but you can't set custom headers on you response directly.
You can use Lambda#Edge function that can inject security headers through CloudFront.
Here is how the process works: (reference aws blog)
Viewer navigates to website.
Before CloudFront serves content from the cache it will trigger any
Lambda function associated with the Viewer Request trigger for that
behavior.
CloudFront serves content from the cache if available, otherwise it
goes to step 4.
Only after CloudFront cache ‘Miss’, Origin Request trigger is fired
for that behavior.
S3 Origin returns content.
After content is returned from S3 but before being cached in
CloudFront, Origin Response trigger is fired.
After content is cached in CloudFront, Viewer Response trigger is
fired and is the final step before viewer receives content.
Viewer receives content.
Below is the blog from aws on how to do this step by step.
https://aws.amazon.com/blogs/networking-and-content-delivery/adding-http-security-headers-using-lambdaedge-and-amazon-cloudfront/
If you are testing through CloudFront, have you made sure you have invalidated the cached objects? Can you try to upload a completely new file and then try accessing it via CF and see if the header is still not there?
Update
Seems like custom metadata will not work as expected as per DOC. Any metadata other than the ones supported by S3 (the ones displayed in the dropdown) will have to be prefixed with x-amz-meta-