Glossary
MIME type
A MIME type — formally a media type — is the short label that states what a piece of content is: `text/html`, `image/webp`, `application/json`. It travels in the `Content-Type` response header, and it is how a browser decides whether to render something, run it, or offer it as a download. The file extension has no authority here: the server's declaration wins, and when the declaration is wrong or absent the browser may guess, which is where the security problems start.
How the label is built
A media type is a type and a subtype separated by a slash: `text/css`, `application/pdf`, `image/svg+xml`. The registry of valid values is maintained by IANA.
Text types take a `charset` parameter — `text/html; charset=utf-8` — which tells the browser how to decode the bytes. Getting it wrong produces the characteristic mangled accented characters known as mojibake.
Binary types do not need a charset. An image or a PDF is decoded by its own format rules.
`application/octet-stream` is the deliberate absence of a claim: unknown bytes. Browsers download it rather than render it, which is sometimes exactly what is wanted.
What happens when the type is wrong
A stylesheet served as `text/plain` is not applied. Browsers refuse to treat a non-CSS type as CSS in standards mode, and the page renders unstyled with no error visible to a visitor.
A JavaScript module served with the wrong type is refused for the same reason, and the module never executes.
An HTML file served as `text/plain` displays its own source code. A text file served as `text/html` is parsed as markup, and any tags inside it become part of the document.
That last case is the security one: a user-uploaded file whose content is HTML, served from your domain with a type that lets it render, executes scripts in your origin. Declaring the type correctly is the fix.
Sniffing, and how to switch it off
When the declared type looks wrong or is missing, browsers have historically inspected the first bytes of the content and made their own determination. That behaviour is called MIME sniffing and is specified so that implementations at least agree.
Sniffing turns a mislabelled upload into an executable document, which is the attack the behaviour enables.
`X-Content-Type-Options: nosniff` tells the browser to trust the declared type and refuse the content if the type is unsuitable for how it is being used. It is a single header with no configuration.
With `nosniff` set, a mislabelled resource fails loudly instead of silently changing meaning — which is the point, and also why setting it sometimes reveals existing mislabelling.
How to check what a server declares
`curl -I https://example.com/style.css | grep -i content-type` prints the declaration for one file.
In the browser's Network panel, the Type column shows the declared type for every request, which makes an inconsistency across a set of assets easy to spot.
Test the uncommon file types specifically: fonts, JSON APIs, SVG images and anything uploaded by users. Web server defaults cover HTML, CSS and JavaScript and are frequently incomplete beyond that.
Check the charset on HTML responses. A UTF-8 document served without a charset declaration is decoded by guesswork, and the guess is not always right.
Frequently asked questions
- Does the file extension decide the MIME type?
- Not for the browser. The server usually derives the type from the extension, but what the browser acts on is the Content-Type header the server sent.
- What does nosniff actually prevent?
- It stops the browser from second-guessing a declared type. A mislabelled file is refused instead of being reinterpreted as something executable.
- Do I need charset on every response?
- On text types, yes — HTML, CSS, JavaScript, plain text and JSON in practice. Binary formats carry their own encoding rules and do not need it.
Sources
Related
VeriFixScan crawls a site and applies its checks to every page it reaches, keeping the evidence behind each finding. Scanning one website is free.
Scan a website