Back to Learn

X-Content-Type-Options Security Header | NOC.org

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/plain or image/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-Type header, 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 TypeContent-Type
HTMLtext/html
CSStext/css
JavaScriptapplication/javascript
JSONapplication/json
JPEGimage/jpeg
PNGimage/png
SVGimage/svg+xml
PDFapplication/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: