I found following security notice on Django website:

Django’s media upload handling poses some vulnerabilities when that media is served in ways that do not follow security best practices. Specifically, an HTML file can be uploaded as an image if that file contains a valid PNG header followed by malicious HTML. This file will pass verification of the library that Django uses for ImageField image processing (Pillow). When this file is subsequently displayed to a user, it may be displayed as HTML depending on the type and configuration of your web server.

Unfortunately there is no addition information how to protect website agains that malicious PNG except:

One class of attacks can be prevented by always serving user uploaded content from a distinct top-level or second-level domain. This prevents any exploit blocked by same-origin policy protections such as cross site scripting. For example, if your site runs on example.com, you would want to serve uploaded content (the MEDIA_URL setting) from something like usercontent-example.com. It’s not sufficient to serve content from a subdomain like usercontent.example.com.

So I have some questions:

  1. How should I configure my webserver (nginx)? Is serving from another domain sufficient?
  2. How can I generate HTML as PNG to upload it on server and ensure it will not displayed as HTML?
  3. Should I add an additional image check on upload and what is best solution/library (libmagick probably) for that?

Also could you explain more detailed how that type of attack works? Does the hacker try to execute JS built in PNG?

  • 1
    basically, just make sure your default mime type is "text/plain", not "text/html" and you should be good. Some servers like to set a content-disposition header or unknown mime, which causes the file to be downloaded instead of rendered to protext the site from such goofs. This is actually a bad idea because users can accidentally execute the downloaded file using something of unknown safety. You can't see/run the html from an <img> tag, it would have to be navigated to, like in a tab, popup, or iframe.
    – dandavis
    Apr 8, 2019 at 18:54
  • @dandavis why exactly "text/plain" and not "image/png"? Apr 8, 2019 at 19:21
  • the default setting should be plain text, so that html doesn't "do anything" when it surreptitiously appears. Images should be images, and that mime is safe as well.
    – dandavis
    Apr 8, 2019 at 19:44


You must log in to answer this question.

Browse other questions tagged .