Home / Knowledge hub / Content-type validation
Knowledge hub
Content-type validation
Checking what a request or upload really is, not just what it says it is.
What it means
Content-type validation is checking that the data you receive is the kind of thing you expected. A request says what it carries in its Content-Type header, and a file arrives with a name and a type. All of that is written by the sender, so none of it is proof.
Real validation looks at the content itself as well as the label. Is this body really JSON? Does this file start with the bytes of a real image? Is this the only type this endpoint takes? Treat the label as a claim and the bytes as evidence.
Why it matters
Trusting the label lets an attacker choose the path. A script uploaded as an image can be served back and run in a visitor's browser. An endpoint that accepts a different body format than the one you tested may use a different parser with different rules. Browsers may even guess a type on their own, which is called content sniffing.
The outcome can be stored XSS, a file upload that runs code on the server, or a way past a CSRF defence that depended on requests being JSON. Each starts with the same assumption: the type is what it says.
How it shows up
You meet it in two places. In APIs, check that the request type matches what the endpoint accepts and answer anything else with an error such as 415. In uploads, check the extension against an allowlist, check the file's real signature, rename the file, store it away from the web root, and serve it with a fixed type.
Set X-Content-Type-Options: nosniff so browsers respect the type you send. The mistakes repeat: checking only the extension, checking only the header, allowing too many types, and keeping the original filename. See file upload vulnerability. Each of these leaves a gap that a carefully named file can pass through.
Questions people ask
Content-type validation, answered
Can I trust the Content-Type header?
No. The client writes it and can put anything in it. Use it as a hint for choosing a parser, then check that the body really matches.
For uploads, also inspect the file itself.
What are magic bytes?
They are the first few bytes of many file formats that identify the format, such as the signature at the start of a PNG. Checking them is stronger than trusting the name.
They are still not enough alone, since a file can be valid in two formats at once.
What does nosniff do?
The header X-Content-Type-Options: nosniff tells browsers to use the type you declared and not to guess a different one from the content.
It stops a file served as plain text from being run as script.
Why would an API reject unexpected content types?
Because each type is handled by a different parser, and each parser has its own quirks. Refusing types you did not plan for narrows what attackers can try.
It also makes some cross-site request attacks harder.
How do we test it?
Upload files with the wrong extension, a mismatched type and a double extension. Send API requests with a different Content-Type from the documented one. Check how each is served back.
Note any case where the app accepts it.
Sources
Where this comes from
Related
Terms that sit next to this one
File upload vulnerability
An upload feature that accepts files it should refuse, such as scripts.
Content sniffing
A browser guessing a file's real type, which can turn an upload into a script.
X-Content-Type-Options
A header that stops browsers guessing a file's type and running it as a script.
Input validation
Checking that what arrives is the shape and range you expected.
Stored XSS
Malicious script saved by your app and then served to other people who view it.
Is the file what it says it is?
We test uploads and request bodies with mismatched types and show the request, the response and where the file ended up. Book a pilot on one app.
Or start with a $199 pilot on one application: thirty days, success criteria agreed before day one, credited against the annual if you convert.