March 26, 2023

Blog @ Munaf Sheikh

Latest news from tech-feeds around the world.

Countering MIME sniffing with X-Content-Type-Options and Content-Type headers

We’ve realized methods to block sure cross-site-scripting (XSS) assaults within the previous article. We did that by disallowing our web site from operating JavaScript from unknown origins. Sadly, attackers may be capable of add malicious code into our utility disguised as a picture, for instance. Then, they will make the most of MIME sniffing to trick a browser into operating it.

This text explains what MIME is and why it’s essential to set our Content material-Kind header accurately. We additionally dive into MIME sniffing and add a layer of safety utilizing the X-Content material-Kind-Choices header.


Multipurpose Web Mail Extensions (MIME) is a regular derived from how emails work, therefore the title. The physique of an electronic mail can include attachments equivalent to movies and pictures. The kind of every attachment is described utilizing MIME to interpret it.

A legitimate MIME kind consists of a kind and a subtype separated by a slash.

The kind describes the information kind class, such because the .

The subtype specifies the precise type of information the MIME kind describes. For photos, it may be , or , for instance.

The MIME kind may also have non-obligatory parameters. A superb instance is a worth that describes the character set used.

An instance of a particular MIME kind is . If you wish to know extra about it, try Node.js TypeScript #6. Sending HTTP requests, understanding multipart/form-data

Content material-Kind

The MIME sorts aren’t solely utilized in emails, although. When a browser requests a useful resource from a given URL, it doesn’t depend on the file extension when processing it. As an alternative, the browser expects the server to reply with a Content material-Kind header. Due to this fact, it ought to include a legitimate MIME kind.

Setting legitimate MIME sorts

In API with NestJS #55. Uploading files to the server, we’ve outlined an API that we are able to use to add and retrieve recordsdata. Let’s say an attacker uploads the next file via our API:


The above code goals to ship the cookies from the web site. If an attacker retrieves he tcookies containing delicate information, equivalent to authentication tokens, the implications will be immense. Due to that, we must always not retailer tokens in common cookies. If you wish to know methods to design a secure authentication mechanism utilizing HttpOnly cookies, try API with NestJS #3. Authenticating users with bcrypt, Passport, JWT, and cookies

Additionally, the identical origin coverage mechanism might cease the above request from occurring. If you wish to know extra, check out Cross-Origin Resource Sharing. Avoiding Access-Control-Allow-Origin CORS error

For the reason that file known as , our API accepts it with out complaining. As a result of the extension is , JavaScript assumes the MIME kind . The essential half occurs when the person tries to entry the uploaded file.

The file will be obtainable at the place 5 is an instance of an id our utility can assign to the uploaded file. Due to this fact, let’s have a look at part of the code that retrieves the useful resource.

Setting informs the browser that it will possibly show the file. If the person tries to put it aside, the browser suggests because the filename.

The essential half above is . Due to doing that, we reply with a legitimate .

MIME sniffing

Let’s assume the URL of our utility is . Think about the attacker manages to inject the next HTML into our web site efficiently:

If we’d arrange our Content material-Safety-Coverage header correctly, the browser wouldn’t execute the above script.

If you wish to know extra concerning the content material safety coverage, try Fighting cross-site-scripting (XSS) with content security policy

Within the above case, we might see the next error within the console:

Refused to load the script ‘’ as a result of it violates the next Content material Safety Coverage directive: “script-src ‘self’”. Word that ‘script-src-elem’ was not explicitly set, so ‘script-src’ is used as a fallback.

To take care of the above restriction, the attacker may additionally attempt injecting the file we’ve seen above that comprises the malicious code.

This time, the URL of the script matches the origin of our web site. The essential factor is that the browser doesn’t care that the script’s filename is . Quite the opposite, it cares concerning the MIME kind. Injecting the above script would lead to a special error than earlier than:

Refused to execute script from ‘https://web’ as a result of its MIME kind (‘picture/jpeg’) isn’t executable.

Fortunately, the browser didn’t execute the malicious script. That is all due to the truth that we arrange the Content material-Kind header accurately. Our framework assigns it with the MIME kind if we don’t do this. The above kind describes generic binary information that we don’t know a lot about.

When the Content material-Kind header of a useful resource is lacking or very generic, equivalent to , or , the browser performs MIME sniffing by default.

Through the above course of, the browser guesses the right MIME kind by wanting on the bytes of the useful resource. Due to that, the browser would interpret as JavaScript and execute it.

X-Content material-Kind-Choices

Guessing the MIME kind by the file’s content material can pose a major menace to our customers if the attackers know methods to make the most of it. Thankfully, we are able to take care of the above difficulty utilizing the header. Moreover, we are able to simply add it via middleware if we use Node.js with Categorical or NestJS.

When the browser fetches , it receives in response. Due to that, it doesn’t carry out MIME sniffing and throws an error as an alternative.

Refused to execute script from ‘https://web’ as a result of its MIME kind (‘utility/octet-stream’) isn’t executable, and strict MIME kind checking is enabled.

We will additionally use the helmet library as an alternative of setting the X-Content material-Kind-Choices header manually. It is because it units extra headers than X-Content material-Kind-Choices and goals to safe our Categorical-based purposes. If you wish to know extra, try the next: Increasing security of Express applications with the Helmet middleware.


On this article, we’ve gone via what MIME kind is and why we must always be sure that we ship appropriate sorts via the Content material-Kind header. If the browser doesn’t have sufficient details about the file kind, it makes an attempt to guess it. The above can result in operating malicious code on our web site and have important penalties. Due to this fact, we must always use the X-Content material-Kind-Choices header to make sure that the browsers don’t attempt to sniff the MIME kind. Doing that makes our utility extra resilient to assaults.

Source link