19

I've been running some penetration tests using OWASP ZAP and it raises the following alert for all requests: X-Content-Type-Options Header Missing.

I understand the header, and why it is recommended. It is explained very well in this StackOverflow question.

However, I have found various references that indicate that it is only used for .js and .css files, and that it might actually be a bad thing to set the header for other MIME types:

  • Note: nosniff only applies to "script" and "style" types. Also applying nosniff to images turned out to be incompatible with existing web sites. [1]
  • Firefox ran into problems supporting nosniff for images (Chrome doesn't support it there). [2]
  • Note: Modern browsers only respect the header for scripts and stylesheets and sending the header for other resources (such as images) when they are served with the wrong media type may create problems in older browsers. [3]

The above references (and others) indicate that it is bad to simply set this header for all responses, but despite following any relevant-looking links and searching on Google, I couldn't find any reason behind this argument.

What are the risks/problems associated with setting X-Content-Type-Options: nosniff and why should it be avoided for MIME types other than text/css and text/javascript?

Or, if there are no risks/problems, why are Mozilla (and others) suggesting that there are?

HappyDog
  • 1,230
  • 1
  • 18
  • 45

3 Answers3

15

The answer by Sean Thorburn was very helpful and pointed me to some good material, which is why I awarded the bounty. However, I have now done some more digging and I think I have the answer I need, which turns out to be the opposite of the answer given by Sean.

I will therefore answer my own questions:

The above references (and others) indicate that it is bad to simply set this header for all responses, but despite following any relevant-looking links and searching on Google, I couldn't find any reason behind this argument.

There is a misinterpretation here - this is not what they are indicating.

The resources I found during my research referred to the header only being respected for "script and style types", which I interpreted this to mean files that were served as text/javascript or text/css.

However, what they actually referring to was the context in which the file is loaded, not the MIME type it is being served as. For example, <script> or <link rel="stylesheet"> tags.

Given this interpretation, everything make a lot more sense and the answer becomes clear:

You need to serve all files with a nosniff header to reduce the risk of injection attacks from user content.

Serving up only CSS/JS files with this header is pointless, as these types of file would be acceptable in this context and don't need any additional sniffing.

However, for other types of file, by disallowing sniffing we ensure that only files whose MIME type matches the expected type are allowed in each context. This mitigates the risk of a malicious script being hidden in an image file (for example) in a way that would bypass upload checks and allow third-party scripts to be hosted from your domain and embedded into your site.

What are the risks/problems associated with setting X-Content-Type-Options: nosniff and why should it be avoided for MIME types other than text/css and text/javascript?

Or, if there are no risks/problems, why are Mozilla (and others) suggesting that there are?

There are no problems.

The problems being described are issues regarding the risk of the web browser breaking compatibility with existing sites if they apply nosniff rules when accessing content. Mozilla's research indicated that enforcing a nosniff option on <img> tags would break a lot of sites due to server misconfigurations and therefore the header is ignored in image contexts.

Other contexts (e.g. HTML pages, downloads, fonts, etc.) either don't employ sniffing, don't have an associated risk or have compatibility concerns that prevent sniffing being disabled.

Therefore they are not suggesting that you should avoid the use of this header, at all.

However, the issues that they talk about do result in an important footnote to this discussion:

If you are using a nosniff header, make sure you are also serving the correct Content-Type header!


Some references, that helped me to understand this a bit more fully:

  1. The WhatWG Fetch standard that defines this header.
  2. A discussion and code commit relating to this header for the webhint.io site checking tool.
HappyDog
  • 1,230
  • 1
  • 18
  • 45
3

I'm a bit late to the party, but here's my 2c.

This header makes a lot of sense when serving User Generated Content. So people don't upload a .png file that actually has some JS code in it, and then use that .png in a <script> tag.

You don't necessarily have to set it for the static files that you have 100% control of.

Alex from Jitbit
  • 53,710
  • 19
  • 160
  • 149
  • 1
    This reply doesn't directly answer the question, but it is a good secondary point. For the reasons you mention (and mentioned in the accepted answer) user-generated content should always be `nosniff`, but if you have 100% control of the static files there may be some benefit in omitting it, to avoid issues if server MIME-type configuration is incorrect. In practice, user-generated content can often be served as static files though, so if this is the case it is probably safer to add `nosniff` to all requests rather than trying to be clever and potentially leave a hole open. – HappyDog Sep 06 '20 at 17:29
  • 1
    @HappyDog I know it does not directly answer, but your question is ranked at the top of Google on how to use this header and what's it for :) – Alex from Jitbit Sep 07 '20 at 17:48
  • I thought that was probably the case, but thought it worth clarifying. And it's always nice to be highly ranked! :-) – HappyDog Sep 08 '20 at 18:20
0

I would stick to js, css, text/html, json and xml.

Google recommend using unguessable CSRF tokens provided by the protected resources for other content types. i.e generate the token using a js resource protected by the nosniff header.

You could add it to everything, but that would just be tedious and as you mentioned above - you may run into compatibility and user issues.

https://www.chromium.org/Home/chromium-security/corb-for-developers

Sean Thorburn
  • 1,728
  • 17
  • 31
  • This doesn't quite answer the question directly, but your description plus the link you have posted have given me a great insight and I think I now have a handle on what the issues are and therefore how this should be handled. I will be writing up a more direct answer to the questions posed, drawing on your information, but in the meantime this answer is more than worthy of the bounty. Thank you! – HappyDog Nov 15 '18 at 19:54
  • Thank you, glad I could help! – Sean Thorburn Nov 16 '18 at 21:28