What Is X-Content-Type-Options?
X-Content-Type-Options is an HTTP security header that prevents browsers from performing MIME-type sniffing on a response. MIME-type sniffing is a browser behavior where the browser ignores the declared Content-Type header and instead tries to determine the file type by inspecting the content itself. While this was originally intended to handle misconfigured servers, it creates a significant security risk that attackers can exploit.
When a browser "sniffs" the content type, it may interpret a file differently than the server intended. For example, an attacker could upload a file with a .jpg extension that actually contains JavaScript. If the browser sniffs the content and detects executable code, it may execute it as a script instead of rendering it as an image. The X-Content-Type-Options header eliminates this risk by telling the browser to strictly follow the declared Content-Type.
The nosniff Directive
X-Content-Type-Options has only one valid directive: nosniff.
X-Content-Type-Options: nosniff
When this header is set, the browser will:
- Block script execution — If a response is served with a non-script MIME type (e.g.,
text/plainorimage/jpeg), the browser will refuse to execute it as JavaScript, even if the content looks like valid JavaScript. - Block style loading — If a CSS file is served with a non-CSS MIME type, the browser will refuse to apply it as a stylesheet.
- Respect the declared Content-Type — The browser will always use the MIME type declared in the
Content-Typeheader, never overriding it based on content inspection.
Why MIME Sniffing Is Dangerous
MIME-type sniffing enables several attack vectors:
Cross-Site Scripting (XSS) via File Uploads
Many web applications allow users to upload files — profile pictures, documents, attachments. An attacker can upload a file named avatar.jpg that contains JavaScript code instead of image data. Without nosniff, a browser might sniff the content, detect JavaScript, and execute it in the context of your domain. This leads to a stored cross-site scripting vulnerability.
Content Injection
If a server returns user-generated content with a generic MIME type like text/plain, a browser performing MIME sniffing might interpret it as HTML. This allows attackers to inject malicious HTML or JavaScript into what the server intended to be plain text.
Polyglot Files
Polyglot files are crafted to be valid in multiple formats simultaneously. For example, a file can be both a valid JPEG image and valid JavaScript. Without nosniff, a browser might execute the JavaScript portion of such a file when it performs content sniffing.
Server Configuration
Apache
Add to your .htaccess file or virtual host configuration:
# Apache — enable X-Content-Type-Options
Header always set X-Content-Type-Options "nosniff"
Make sure mod_headers is enabled: a2enmod headers && systemctl restart apache2
Nginx
Add to your server block:
# Nginx — enable X-Content-Type-Options
add_header X-Content-Type-Options "nosniff" always;
Node.js / Express
app.use((req, res, next) => {
res.setHeader('X-Content-Type-Options', 'nosniff');
next();
});
Or use the Helmet middleware which sets this header by default.
WordPress / PHP
<?php
header('X-Content-Type-Options: nosniff');
?>
Correct Content-Type Headers
For nosniff to work correctly, your server must send the proper Content-Type header for every response. Common MIME types:
| File Type | Content-Type |
|---|---|
| HTML | text/html |
| CSS | text/css |
| JavaScript | application/javascript |
| JSON | application/json |
| JPEG | image/jpeg |
| PNG | image/png |
| SVG | image/svg+xml |
application/pdf |
If your server sends the wrong Content-Type (e.g., serving JavaScript as text/plain), nosniff will block the browser from executing it. This is intentional — it forces you to fix your server configuration rather than relying on browser guessing. For a deeper understanding of MIME types, see What is a MIME Type?
Browser Support
X-Content-Type-Options is supported by all modern browsers:
- Chrome (all versions)
- Firefox (all versions)
- Safari (all versions)
- Edge (all versions)
There is no reason not to set this header. It has universal support, no negative side effects when Content-Types are configured correctly, and provides meaningful protection against MIME sniffing attacks.
Testing Your Configuration
After adding the header, verify it's working:
# Check response headers with curl
curl -I https://example.com
# Look for this line in the output:
# X-Content-Type-Options: nosniff
You can also check your security headers using the security headers overview guide or online scanning tools.
Related Security Headers
X-Content-Type-Options works best as part of a comprehensive security headers strategy. See our guides on: