Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CORS error when attempting to upload non-image to ImageField #254

Open
agsimmons opened this issue Mar 29, 2023 · 3 comments
Open

CORS error when attempting to upload non-image to ImageField #254

agsimmons opened this issue Mar 29, 2023 · 3 comments
Assignees

Comments

@agsimmons
Copy link
Contributor

agsimmons commented Mar 29, 2023

If you have an ImageField, and try to upload a non-image file, the POST request initiated by s3file.js to the S3 bucket fails with a CORS error.

In Firefox, the error is Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://bucketname.s3.amazonaws.com/. (Reason: CORS request did not succeed). Status code: (null).

If you instead upload a valid image file to that same field, the request succeeds with no CORS error.

If you change the extension of a non-image file to .png, and upload it to the ImageField, there is no CORS error but the "Upload a valid image. The file you uploaded was either not an image or a corrupted image." error is displayed as expected.

My expectation is that if you try to upload a non-image file to an ImageField, it would be uploaded to tmp/s3file/ with no CORS error. The field validators would then execute, which would recognize that the uploaded file is not an image or doesn't have the correct extension, then an error would be returned and displayed to the user like normal. Alternatively, I would expect there to be no CORS error but instead a 4xx response from S3 if the content type is not allowed.

I haven't yet been able to identify why this is happening. I see that in the inputs data-fields-policy, it specifies ["starts-with", "$Content-Type", "image/"], but I don't know how this could cause a CORS error.

@agsimmons agsimmons changed the title CORS error when attempting to upload non-images to ImageField CORS error when attempting to upload non-image to ImageField Mar 29, 2023
@codingjoe
Copy link
Owner

Hi @agsimmons,

Thanks for reaching out. This is interesting, I haven't seen this before. How did you stumble on this error? Yes, the policy is set to specific content types, if they are defined for the input. This is done to add a little backend validation, since you can't trust users. However, this is rudimentary at best and I would always suggest properly vetting user input, to avoid injections.

Anyhow, I believe Firefox is just displaying this as a CORS error, since yes, the request is CORS and didn't succeed. However, if you go to the network tap and select XHR, you will probably find the server response from S3. I don't know what they respond, but most likely with a 400 or a 403.

I didn't write any error handling for failed requests, since they shouldn't happen. S3s uptime is exceptional, and the interface should prevent users from selecting files not meeting the accept attribute. Thus, my curiosity about how you stumbled upon this issue.

Best!
Joe

@codingjoe codingjoe self-assigned this May 24, 2023
@agsimmons
Copy link
Contributor Author

I should have mentioned that this was in the Django admin interface specifically.

In the admin interface, ImageFields inputs are created with the accept="image/*" attribute, which should tell the browser to only allow image files, but Firefox (on Linux at least) seems to ignore this by default and allow you to choose any file. I accidentally chose a video file for this input, and tried to save the model in the admin interface. Nothing happened, so I looked in the console and noticed this error.

Without django-s3file following these same steps, the video file is uploaded, then Django validates that it is actually an image file. That fails, and then an error is shown to the user in the admin interface. This isn't great as it wastes time uploading an invalid file, but that's why I had that expectation.

Maybe this isn't an issue with django-s3file and is just due to a lack of client-side input validation.

Below are screenshots of the network inspector. Upon saving the model, two requests are made. The first OPTIONS requests succeeds, and the second POST request fails with the CORS error. It appears that it really is a CORS error, and the request never makes it to S3.

1
2
3
4
5

Thanks!

@codingjoe
Copy link
Owner

Hi there, thanks for the details. It does seem to be a CORS issue, since the browsers is preventing the request. Can you share your Access-Control-* headers with me? Of the original site, not the XHRs?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants