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
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" },
],
},
];
},
};Add the directive to your server block so it applies to all responses proxied through nginx.
add_header X-Content-Type-Options "nosniff" always;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.
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 freeRelated guides
Content-Security-Policy (CSP): what it is and how to add one
The header that stops injected scripts from running.
Clickjacking and X-Frame-Options: keep your pages out of iframes
One header stops attackers from overlaying your app inside an iframe.
Open directory indexes: when your file server lists everything
A file server that lists its contents hands attackers a free inventory.