Back to Glossary
low severity · Vulnerability Glossary

MIME Sniffing (Missing X-Content-Type-Options)

Updated August 8, 2026

4 min read

mime sniffing
x-content-type-options
nosniff header
mime sniffing vulnerability
content-type-options missing
content sniffing
mime type security
security headers

MIME sniffing is when a browser ignores the Content-Type a server declares and guesses the type from the response bytes instead — so a file the server labels as plain text can be treated as HTML or JavaScript. A missing X-Content-Type-Options: nosniff response header is what allows it; you detect the gap with a one-line curl check and close it by sending that header alongside correct, specific Content-Types.

What is MIME sniffing?

Every response your server sends carries a Content-Type header — text/html, application/json, image/png — telling the browser how to interpret the bytes that follow. Historically, browsers didn't fully trust it: to be forgiving of misconfigured servers, they would "sniff" the actual bytes and, if the content looked like something else, render it as that instead. A text/plain response whose body starts with <html> could be rendered as a web page.

X-Content-Type-Options: nosniff turns that guessing off. It tells the browser to honor the declared Content-Type — refusing to run a response as script, or apply it as a stylesheet, unless the type actually matches (text/javascript, text/css). When the header is absent, the browser falls back to its legacy sniffing behavior.

This maps to OWASP A05: Security Misconfiguration: a standard hardening control that ships off by default on most stacks, so it's usually just never been set.

Why it's a risk / how it's exploited

Sniffing can promote inert content into executable code inside your origin. If an attacker gets bytes that look like HTML or JavaScript into a response the browser sniffs, that content can run as script in your site's security context — a path to cross-site scripting or a drive-by.

Concrete scenario: your app lets users upload a "profile document" and serves it back from your own domain as Content-Type: text/plain. An attacker uploads a file whose body is valid HTML with an embedded <script>. Another user opens it; with no nosniff header, the browser sniffs the HTML, renders it, and runs the script under your origin — reading cookies, making authenticated requests, defacing the page.

The honest framing: this is a hardening header, not a live exploit on its own. On a static site that already sends correct, specific Content-Types, the practical risk is low — there's nothing to misinterpret. It rises when your app serves user-controlled or uploaded content, or returns text/JSON from endpoints an attacker can influence — which is why the bare finding is rated low, more urgent on sites that host uploads. It pairs with other header gaps like clickjacking protection and a Referrer-Policy.

How to detect it

Check for the header from the command line:

curl -sI https://example.com | grep -i x-content-type-options

If it prints X-Content-Type-Options: nosniff, sniffing is disabled and you're covered; if it returns nothing, the header is missing — that's the finding. You can also check in browser DevTools under Network → Response Headers.

To review this alongside your other headers in one pass, run the security headers checker. For the full picture across your site, a website vulnerability scan flags the missing header alongside the rest of your OWASP Top 10 exposure.

How to fix it

Do two things: send the header everywhere, and make sure your declared Content-Types are actually correct — nosniff is a backstop, not a substitute for the right type.

Send the header site-wide at the web server or CDN.

nginx (inside the server block):

add_header X-Content-Type-Options "nosniff" always;

Apache (mod_headers enabled):

Header always set X-Content-Type-Options "nosniff"

Reload (nginx -s reload or apachectl graceful) and re-run the curl check to confirm.

Then close the gap nosniff only backstops:

  • Serve specific, correct Content-Types. Return application/json for API responses (not text/html), the right image/* for media, and text/javascript/text/css for scripts and styles. With accurate types, there's nothing to sniff.
  • Isolate user uploads. Serve user-uploaded files from a separate origin or sandbox domain, so even a sniffed-and-executed file runs outside your main site's cookies and DOM.

Caveat on nginx: add_header does not inherit into a location block that defines its own add_header directives — if you set headers per-location anywhere, repeat the nosniff line there too.

FAQ

Does nosniff alone prevent XSS from uploaded files? No. It stops the browser from sniffing a mislabeled response into script, but a file you serve with an actual text/html Content-Type still renders. Set correct Content-Types and isolate uploads on a separate origin too.

Isn't MIME sniffing an old-browser problem that's already fixed? No. Current browsers still fall back to content sniffing when the header is absent — nosniff is opt-in, so without it you get the legacy behavior. Sending it explicitly closes the finding and passes audits.


Not sure which of your responses ship without nosniff? Run a free website vulnerability scan to check your security headers and the rest of your web attack surface in one pass.