Skip to main content
All fixes

SSL, TLS, security headers

Add X-Content-Type-Options nosniff to block MIME sniffing

Without nosniff, browsers may sniff MIME types and execute uploaded files as scripts. Set X-Content-Type-Options: nosniff on every response.

What's happening

MIME sniffing is the browser behavior of inferring a resource's content type from its bytes when the server-supplied Content-Type seems wrong. Internet Explorer 6 popularized this; modern browsers still do it under specific conditions. The result is that a file the server marked as text/plain can be executed as JavaScript or rendered as HTML if the body looks script-like, opening a path for stored XSS via uploaded files.

X-Content-Type-Options: nosniff disables MIME sniffing for the response. The browser will treat the resource exactly as the server-declared Content-Type says — script/css/json/etc. — and refuse to execute mismatched content. The header has only one valid value, nosniff, and it should be on every response.

The fix is trivial: set the header globally in your web server or framework. There is no functional downside as long as your application sends correct Content-Type values, which it should anyway.

Why it matters

An attacker who can upload a file (avatar, attachment, document) and link to it can sometimes get the browser to execute it as JavaScript, which is stored XSS. The same risk applies to any user-submitted content served from your origin.

Without nosniff, even a correctly-configured CSP can be bypassed if the attacker uploads a file the browser sniffs as script. nosniff closes that gap.

Mozilla Observatory and SecurityHeaders.com penalize the missing header. PCI-DSS 4.0 lists MIME-sniffing protection as a required control on user-content-serving applications.

Common causes

  • Web server defaults do not include the header.
  • A specific upload route was excluded from the global header for a reason no longer remembered.
  • The header is set on HTML routes but missing on the /api/upload handler that serves user files.
  • A CDN strips response headers it does not recognize from older origins.
  • Cloudflare Page Rules accidentally rewrite a path's headers.

Detect this on your site

Run a quick scan with the Full Site Audit. The tool surfaces this exact issue with the records and context needed to apply the fix below.

Open Full Site Audit

How to fix it

  1. 1

    Confirm the header is missing

    Run curl -sI https://example.com | grep -i x-content-type-options. If nothing prints, the header is missing. Repeat for any file-serving routes — curl -sI https://example.com/uploads/foo.png — to confirm coverage everywhere.

  2. 2

    Set the header globally in nginx

    Add add_header X-Content-Type-Options "nosniff" always; to the http or server block. The always parameter ensures it is sent on error responses too. Reload nginx with sudo nginx -t && sudo systemctl reload nginx.

  3. 3

    Set the header globally in Apache

    Add Header always set X-Content-Type-Options "nosniff" in the VirtualHost or in .htaccess. Confirm mod_headers is enabled with a2enmod headers. Reload with sudo systemctl reload apache2.

  4. 4

    Set on Cloudflare or your CDN

    In Cloudflare, use Transform Rules → Modify Response Header → Set 'X-Content-Type-Options' to 'nosniff' on every request. Fastly: add to your VCL response handler. The CDN is the cleanest place to set headers globally regardless of origin.

  5. 5

    Verify Content-Type on user-uploaded files

    While you are auditing, make sure every user-uploaded file is served with an accurate Content-Type. Avatars should be image/png or image/jpeg, never application/octet-stream. Combine nosniff with explicit Content-Type and ideally a Content-Disposition: attachment for downloads.

  6. 6

    Re-audit and lock in

    Re-run the Full Site Audit at /check. Mozilla Observatory should grade higher. Add a CI check or smoke test that asserts the header is present on representative routes.

Example

# In the http block so every server inherits
http {
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "DENY" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}

Nosniff alongside other baseline security headers

Frequently asked

Only if your application is sending incorrect Content-Type values — for example JSON responses labeled as text/plain. nosniff will refuse to execute or render those resources as their sniffed type. The fix is to set Content-Type correctly at the source which is a good practice regardless.

No. nosniff prevents MIME-type confusion attacks; CSP restricts which sources can be loaded and executed. They are independent and complementary. Set both.

Related fixes