Glossary
X-Content-Type-Options
`X-Content-Type-Options: nosniff` tells a browser not to second-guess the `Content-Type` a server declared. Without it, a browser encountering content that looks unlike its declared type may inspect the bytes and reinterpret it — which turns a mislabelled upload into an executable document served from your origin. The header takes one value, has no configuration, and is the cheapest security header there is.
What sniffing is and why it existed
Browsers historically inspected the first bytes of a response when the declared type looked implausible, because a large share of the early web declared types badly or not at all.
The behaviour is now specified so that implementations at least agree on what they guess, but it remains a guess.
The security consequence is direct: a file a user uploaded, stored as text, and served from your domain can be sniffed as HTML and rendered, executing any script inside it in your origin.
That is a cross-site scripting vector that requires no flaw in your application code beyond serving the file.
What nosniff enforces
The declared type is used as given. Content that does not match how it is being used is refused rather than reinterpreted.
A stylesheet not served as a CSS type is not applied. A script not served as a JavaScript type is not executed.
The header applies to every response it is set on, and setting it globally at the web server is the normal arrangement.
It does not affect images, video or anything the browser decodes by format rather than by declaration.
It also blocks a cross-origin resource whose declared type does not match how it is being used, which is part of the wider cross-origin read blocking behaviour browsers apply.
What it can break, and why that is useful
A site with mislabelled stylesheets or scripts will find them refused once the header is set. This is the header revealing a pre-existing fault rather than causing one.
The correct response is to fix the declared types, not to remove the header. A resource served with the wrong type is already fragile.
The most common offenders are fonts, JSON endpoints, and files served from a directory with no type mapping configured.
Deploying to a staging environment first turns this from an incident into an afternoon.
How to check it
`curl -I https://example.com | grep -i x-content-type-options` shows whether it is present.
Check it on assets as well as on the document, since header configuration is frequently applied to one and not the other.
Check the declared types of stylesheets, scripts, fonts and JSON at the same time; these are what the header will enforce.
There is no value other than `nosniff`, so the check is presence rather than correctness.
Where user uploads are served, check that they are also served from a separate origin or with a download disposition. The header prevents reinterpretation; it does not prevent a genuinely HTML upload being declared as HTML.
Frequently asked questions
- Are there any downsides to setting nosniff?
- Only that mislabelled resources stop working. That is a pre-existing fault the header reveals, and the fix is to declare the correct types.
- Does nosniff affect images?
- No. It governs whether content is reinterpreted as a different type for styles and scripts. Images are decoded by their own format rules.
- Where should the header be set?
- Globally at the web server or CDN, so it applies to every response rather than only to HTML documents.
Sources
Related
VeriFixScan crawls a site and applies its checks to every page it reaches, keeping the evidence behind each finding. Scanning one website is free.
Scan a website