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

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.

Related

Django admin Resource Policy COEP ERR_BLOCKED_BY_RESPONSE

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.

What's the http request for the page source?

I've managed to make a file downloader in C++ (using winsock). It downloads every simple link with a file like: www.page.com/image.png
I want to make it download all of the images from an entire page, such as all the images from a 4chan thread, but I don't know what I should send in the http request to get the page's source. How can I request the source of a webpage?
You don't send anything in the http request, in the manner you're thinking.
An http request sends a single request, for a single document, and returns a single document from the server.
To download an entire page, you will have to parse the downloaded HTML document, extract all the relative links from the HTML source, then issue a separate http request for every image, css, js, etc... referenced from the main document.
This is how tools like wget's --recursive option download entire pages.
If the page is located at the root of the http://www.page.com server, you would send a GET request to the www.page.com server asking for the / resource:
GET / HTTP/1.1
Host: www.page.com
Let's say the page was actually located at http://www.page.com/thepage.html. You would send a GET request asking for /thepage.html instead:
GET /thepage.html HTTP/1.1
Host: www.page.com
Either way, you would then have to parse the resulting HTML to get the individual URLs of all the <img> tags that are on the page.

request.POST empty for Content-Type: multipart/form-data; boundary=xYzZY

[SOLVED] Please see my answer.
Any POST request sent with the
Content-Type: multipart/form-data; boundary=xYzZY results in the request.POST QueryDict{} to be empty. Changing the Content-Type to multipart/form-data also results in the same error.
Removing the Content-Type altogether results in the values getting passed correctly, and I can access them in request.POST.
I have tried disabling the Csrf middleware, using #csrf_exempt, and also tried the same on multiple servers. Didn't change the empty POST condition.
While reading up on Django framework and POST content-type, I read that it (no longer) assumes a default content-type and therefore must be supplied with the correct one (I do not have a link to the article in question.) I think something similar is happening here, with django not being able to parse the parameters with the given content-type (but leaving it blank lets the parser interpret it with the default value).
What I am having trouble with is, that the Content-Type value supplied is perfectly valid (multipart/form-data with boundary). So why does django refuse to load it in the POST dictionary?
** I am not in control of the Content-Type sent in the POST data.
** UPDATE: reading from request.body shows that all the POST parameters are being received. They're just not present in request.POST
** UPDATE: I'm using Runscope to test POST requests.
As mentioned in the UPDATE, I was using Runscope to test the POST data. I realised that the error was with the way Runscope handled multipart/form-data. I raised the issue with support and got notified that Runscope does not support multipart as of now. I've copied the relevant information here:
We hope to support multipart form uploads capabilities for the future, but don't have a timeline on when this will be available. Some customers have made this work in their Radar tests (https://www.runscope.com/docs/radar) by pasting in the raw multipart-formatted body or unicode string input body into the request and making sure to include the applicable 'Content-type' header value with the correct boundaries. Some examples for building a multipart/form-data POST request can be found here: http://chxo.com/be2/20050724_93bf.html
For Runscope URLs, multipart data is passed through unmodified. However, the request editor and retries from the Traffic Inspector (https://www.runscope.com/docs/inspector) do not currently support multipart data which is why your request retry did not work. Additionally, request and response bodies larger than 1 MB are not saved for viewing after the request has been sent.
Using another service solved this for me.
You are (in a manner) in control of Content-Type. What you're looking for is enctype. You can use it as following:
<form method="POST" action="." enctype="multipart/form-data">
enctype is only required when you are uploading a file, otherwise, it's not.

Why isn't Ember.js seeing the Access-Control-Allow-Origin header from my server?

My app is an Ember.js front end with a Go API on the server. I created the Ember app using the FixtureAdapter. Now that I have the Go API back end I converted it to RESTAdapter.
When I hit my API directly with the browser, I seem to get the appropriate CORS headers back:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Origin,x-requested-with
Access-Control-Allow-Methods:PUT,PATCH,GET,POST
Access-Control-Allow-Origin:*
Access-Control-Expose-Headers:Content-Length
However, when my Ember.js app hits the API, I get XMLHttpRequest cannot load https://192.168.59.103:8001/notifications. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://192.168.59.103:9000' is therefore not allowed access..
I don't know how else to see what's going on between Ember and the API. I've read this CORS tutorial and everything seems to be okay on the server end.
I included the bit about x-requested-with because of another Stack Overflow question suggesting that jQuery requests need something different than plain old JavaScript requests.
Your endpoints also need to respond with CORS headers to OPTIONS requests- those will execute before the actual request to make sure that the request is allowed first.
Do you happen to be using Nginx as your reverse proxy for your API? If so, we experienced this same issue. In our case, the problem was that Nginx returns the correct CORS headers just fine for HTTP 200 OK responses, but for any error response, it will fail to add the COR headers and therefore the actual server response gets obscured by the browser complaining that it doesn't have the appropriate CORS headers to render a response.
See https://serverfault.com/a/431580/199943.
Even if you're not using Nginx, try calling your API directly (e.g. using Postman to avoid the CORS restrictions to see what it's returning. If your API is returning anything other than an HTTP 200 OK, that may be why the CORS headers aren't getting added.

Differentiate nginx behaviour depending on URL

I have a Django application and I use nginx to serve static content. Unfortunately, all registered MIME types get displayed in client browser, while I would like to give an ability to download the same content, along with usual behaviour. Say, I have JPEG file under /media/images/image01.jpg and I want that nginx serves this file in usual way, with standard image/jpeg header, but additionally I want the same image to be served by nginx with content-disposition: attachment (effectively forcing content download) when accessed as, say, /downloads/images/image01.jpg. Anybody can suggest a solution?
Make sure you have the http_headers_module compiled in. (should be by default, if it isn't in the core)
Use "add_header content-disposition attachment;"
I recommend using a url like "/download?file=/downloads/images/image01.jpg" combined with a rewrite rule to avoid some annoying bug later.
Http Headers Module Documention