All guides
Medium severitySecurity Headers

MIME sniffing and X-Content-Type-Options: nosniff explained

Browsers can "sniff" the actual content of a response to decide how to handle it, even when your server sends the wrong Content-Type. The X-Content-Type-Options: nosniff header tells the browser to trust the declared type and refuse to promote files — like an uploaded image — into an executable script.

What it is

MIME sniffing is a browser heuristic that inspects the first bytes of a response to infer its content type when the server's Content-Type header is absent or doesn't match the content. For example, a file declared text/plain that starts with <script> might be re-classified and executed as HTML.

X-Content-Type-Options is a single-value response header: X-Content-Type-Options: nosniff. When present, browsers refuse to promote a response to a different MIME type — an uploaded file served as application/octet-stream stays binary, never becomes a runnable script or stylesheet.

Why it matters

User-generated content is the main risk. If your app lets users upload files and you serve them from the same origin as your app (or a subdomain that shares cookies), a malicious HTML file disguised as an image can execute in victims' browsers when sniffed — a stored XSS via file upload, even when you validate extensions server-side.

Without nosniff, browsers may also execute stylesheets fetched from unexpected sources. A stylesheet that executes as a script creates a cross-origin data exfiltration path when combined with other misconfigurations. nosniff is a cheap, global safeguard that tightens every content boundary your app has.

How to fix it

Add the header globally in Next.js

Set X-Content-Type-Options: nosniff in next.config.js so it applies to every response, including API routes and static file routes.

// next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: "/:path*",
        headers: [
          { key: "X-Content-Type-Options", value: "nosniff" },
        ],
      },
    ];
  },
};
Set it in nginx

Add the directive to your server block so it applies to all responses proxied through nginx.

add_header X-Content-Type-Options "nosniff" always;
Always declare an accurate Content-Type

nosniff is most effective when every response also carries a correct Content-Type header. For user-uploaded files, serve them with an appropriate type (e.g. image/png for PNG files) and from a separate origin or storage domain — not the same origin as your app — so that even if a file executes, it can't access your users' session cookies.

Validate uploads by content, not just extension

Extension checks can be bypassed. Use a library such as file-type (npm) to inspect the actual file magic bytes server-side, and reject anything that doesn't match an allowlist of safe types before it ever reaches your storage layer.

import { fileTypeFromBuffer } from "file-type";

const ALLOWED = new Set(["image/jpeg", "image/png", "image/webp", "image/gif"]);

async function validateUpload(buffer: Buffer): Promise<void> {
  const type = await fileTypeFromBuffer(buffer);
  if (!type || !ALLOWED.has(type.mime)) {
    throw new Error("Upload rejected: unsupported file type");
  }
}

FAQ

What severity does AppSafe report for a missing X-Content-Type-Options header?

Medium. The header is a low-friction hardening measure — one line of config — so omitting it is a clear gap, but active exploitation requires a separate upload or injection vector.

Does nosniff affect normal page loads?

Not in practice. nosniff only blocks promotion to a more dangerous type. Your HTML, CSS and JavaScript are already served with the correct types, so they load normally.

Is X-Content-Type-Options still relevant now that modern browsers are smarter?

Yes. Browser sniffing behaviour varies between engines and versions, and the header is the only portable guarantee. All current browsers (Chrome, Firefox, Safari, Edge) honour nosniff.

Is your app affected?

AppSafe checks for this and dozens of other issues in one free scan.

Scan my app free