MIME-Handling Changes in Internet Explorer


Each type of file delivered from a web server has an associated MIME type (also called a “content-type”) that describes the nature of the content (e.g. image, text, application, etc). Back in Internet Explorer 8, we made a few changes to IE’s MIME-sniffing feature that attempts to determine the actual content-type for each downloaded resource. In this post, I discuss how recent changes to IE further improve MIME-handling and make browsing more secure.

Certain HTML elements (LINK and SCRIPT in particular) historically have not attempted to validate the MIME-type supplied by the server. For instance, all browsers will run script even if the SCRIPT’s SRC attribute points at a file declaring that it is text/plain. This can lead to a variety of security vulnerabilities, particularly for LINK elements. There is a rich object model for interacting with stylesheets, and this object model can be abused if the “stylesheet” contains other content.

In an attack scenario, a malicious site could include a LINK reference pointing at another site’s HTML content. If that HTML content contained certain common characters, its content could be read by script in the attacker’s page. This information disclosure could lead to cross-site request forgery and other attacks against web applications. You can learn more about this threat in a paper from Carnegie-Mellon University.

In the October Cumulative update, a change was made to CSS handling in IE6, IE7, and IE8 to block all cross-origin stylesheets unless they have been delivered with the proper HTTP response header:

    Content-Type: text/css

This protection helps ensure that LINK and @IMPORT cannot be used as a vector to steal content from another site.

Internet Explorer 9 Beta already included this protection. Additionally, the F12 Developer Tools’ Console included in IE9 shows the following warning message when a cross-origin stylesheet with an incorrect MIME-type is encountered:

IE9 F12 Developer Tools displaying MIME-type mismatch for CSS

Further IE9 Improvements

Beyond the cross-origin stylesheet validation introduced for all versions, Internet Explorer 9 Beta includes some other important changes to MIME-handling behavior to improve security and standards-compliance. These changes could cause problems when displaying content if the Content-Type information is missing or incorrect. The three MIME-handling changes introduced by IE9 are:

  1. In IE9 Standards Mode, even same-origin stylesheets will be ignored unless they are delivered with a text/css MIME type.
  2. SCRIPT elements will reject responses with incorrect MIME types if the server specifies X-Content-Type-Options: nosniff.
  3. Documents delivered with a text/plain MIME type will not be MIME-sniffed to another type.

Change #1 is a requirement of the CSS specification and applies MIME-type validation to same-origin stylesheets when if document is running in IE9 Standards Mode. A concise test case displays red text if a browser applies styles from a stylesheet with an incorrect MIME-type; it renders the text in green if the invalid stylesheet is correctly ignored.

Change #2 impacts the browser’s behavior when the server sends the X-Content-Type-Options: nosniff header on its responses. If the nosniff directive is received on a response retrieved by a SCRIPT reference, IE will not load the “script” file if the MIME type does not match one of the following values [“text/javascript”, “application/javascript”, “text/ecmascript”, “application/ecmascript”, “text/x-javascript”, “application/x-javascript”, “text/jscript”, “text/vbscript”, “text/vbs”]. When such content is blocked, the F12 developer tools show the following message:

IE9 F12 Developer Tools displaying MIME-type mismatch for SCRIPT

This new protection recently impacted a major site which was delivering JSONP responses with a nosniff header but without a proper JavaScript MIME-type. The site owners have since corrected the misconfiguration.

Change #3 is perhaps the most welcome for many web developers. If IE9 encounters a HTML document delivered with a text/plain content-type, the document will be rendered as plain text unless the site is rendering in Compatibility View. This is useful for web developer scenarios because it allows easier sharing of HTML source code snippets. It’s also a welcome change from a security point-of-view, because IE9 will be less susceptible to script injection attacks in files delivered with a text/plain Content Type.

If you find any sites which are sending improper MIME types and behave incorrectly in Internet Explorer, please file a bug on Connect!

Thanks,
Eric Lawrence
Program Manager

Comments (17)

  1. Zack Weinberg says:

    This is great to hear.

    What are the IE team's plans regarding UTF-7?  As you may know, HTML5 requires browsers not to support it, and all available evidence is that on the public web it's only used for exploits (specifically, for "universal XSS" bypass of server-side filters).

  2. Just another web guy says:

    Nice to see the PLAIN/TEXT changes.

  3. jabcreations says:

    IE9 fails to handle malformed XHTML as application/xhtml+xml like Safari/WebKit, Gecko/Firefox and Presto/Opera correctly kill the page and display an error message.

    Now I've seen IE 5/6/7/8 handle malformed XML served as application/xml so I don't see why this wasn't implemented? Instead IE9 attempts to parse the page and does so badly as does Safari. Are you guys going to have this fixed before IE9 ships?

  4. William J. Edney says:

    Eric -

    Thanks for the update (and for your willingness to be on these forums as much as you are ;-) ).

    On a related note to this discussion, are there any plans to support the"overrideMimeType" method for XMLHttpRequest for IE9, as it is supported in other browsers?

    Cheers,

    - Bill

  5. KS says:

    I welcome the stricter checking of MIME-type, but I don't see that #1 really enhances security.

  6. Patrick Garies says:

    Nice changes. #3 has been requested forever. IIRC, Mozilla changed their behavior to match the broken IE behavior awhile back. I wonder what they're going to do now.

    It's also nice to see support for application/javascript and application/ecmascript. Is this also supported on the |script| element's |type| attribute? How about the |version| parameter for those MIME types (specified by the same document that specifies those MIME types)?

    Now if only ya'll would support the correct MIME types for XSLT (application/xml and application/xslt+xml). (The XSLT 2.0 spec still claims that the latter is still undergoing IANA review, but it appears to have been approved.) As far as I can tell, there's no way to get an XSLT-styled document to work in both WIE and non-WIE browsers while following a standard and the touted "same markup" principle. You have to use an |xsl-stylesheet| PI with |type="text/xsl"| instead.

    @jabcreations: Given that your first paragraph doesn't make sense (due to grammatical errors), I'm not sure what you're trying to say.

    If you're saying that WIE is emulating Safari by parsing the document up to the error and rendering the part of the document processed up to that error, that would seem to be permitted by the XML 1.0 spec. From a user perspective, that makes a lot more sense too; I'd presume that most users would rather see /some/ content instead of an error message. (It still needs to be obvious that an error occurred though.)

  7. Patrick Garies says:

    Nice changes. #3 has been requested forever. IIRC, Mozilla changed their behavior to match the broken IE behavior awhile back. I wonder what they're going to do now.

    It's also nice to see support for application/javascript and application/ecmascript. Is this also supported on the |script| element's |type| attribute? How about the |version| parameter for those MIME types (specified by the same document that specifies those MIME types)?

    Now if only ya'll would support the correct MIME types for XSLT (application/xml and application/xslt+xml). (The XSLT 2.0 spec still claims that the latter is still undergoing IANA review, but it appears to have been approved.) As far as I can tell, there's no way to get an XSLT-styled document to work in both WIE and non-WIE browsers while following a standard and the touted "same markup" principle. You have to use an |xsl-stylesheet| PI with |type="text/xsl"| instead.

    @jabcreations: Given that your first paragraph doesn't make sense (due to grammatical errors), I'm not sure what you're trying to say.

    If you're saying that WIE is emulating Safari by parsing the document up to the error and rendering the part of the document processed up to that error, that would seem to be permitted by the XML 1.0 spec. From a user perspective, that makes a lot more sense too; I'd presume that most users would rather see /some/ content instead of an error message. (It still needs to be obvious that an error occurred though.)

  8. Roman says:

    I wish you'd stop involving MIME into this, and start calling them by their real designation — media types.

    tools.ietf.org/…/rfc2616

  9. EricLaw [MSFT] says:

    @Roman: "media types defined by MIME specifications" would be more accurate, but in various places, RFC2616 refers to MIME's media types as simply "types" and I don't think there's any confusion about the term "MIME type".

    @Patrick: I don't believe Mozilla will "sniff" text/plain either, although their download manager has some features to accomodate types that are delivered as "text/plain" but really contain binary content.

    @KS: #1 is about standards-compliance. #2 and #3 are about security.

    @William J. Edney: Do you know of any sites that require the overrideMIMEType method to behave properly?

    @Zack Weinberg: Various changes have been made over the years such that IE8+ will not "autodetect" UTF-7 content, and will only support it if the page explicitly declares that encoding via the Content-Type declaration. A bug present in IE8 related to cross-frame inheritence of character set was fixed and is no longer a vector for UTF-7 abuse.

  10. jabcreations says:

    @Patrick Garies XHTML when correctly served as application/xhtml+xml is supposed to be well formed meaning lacking malformed XML. If an error occurs the page is supposed to break and display an error message.

    The point of this is to encourage better written code. Browsers should only support this mode ANY WAY, so much time is wasted in browser development to determine how to interpret how to handle non-code that looks like code.

  11. anon says:

    @jab

    That non-graceful error handling doesn't work in the "real world" for users. Gracefully handling incorrect HTML is far better than the "Yellow Screen of Death" that Firefox presents when XML is invalid. Like the end user has ANY idea what that XML error is or what  XML even is. You could make the argument that JavaScript already doesn't fail gracefully and that's partially true, though it doesn't take the whole page down if it blows up due to a syntax error or missing function. Chrome and Safari handle it slightly better, but what's wrong with just switching parsers? The goal shouldn't be to punish developers (which hurts users) but to provide the best standards experience for users. Given that Webkit and Gecko handle XML errors differently I'm inclined to believe there isn't a good standard as to how to handle XHTML parsing failures for browsers.

  12. jabcreations says:

    @anon It works for users to tell them the site they are visiting isn't correctly coded whereas if they don't see the error message then they will expect that same broken code to work. I'd rather know a site has an error and come back later…if at all. What you're saying makes no sense because if designers (and developers outsourced to do design) aren't aware of errors then they aren't going to know to fix them.

    Actually the best way to handle the issue is how Opera handles it, offer to render the page as regular HTML when displaying the malformed XHTML error message.

  13. Patrick Garies says:

    @jabcreations: I know the difference between XML and HTML MIME types.

    What I was saying is that the XML spec does not mandate that you replace everything processed with an error message (i.e., the "yellow screen of death") when an error is encountered. It requires that processing stop, but doesn't otherwise say what should be rendered. Some implementors have chosen to render the code that was already processed before the parser hit the XML error.

  14. the_dees says:

    text/plain and others are still sniffed for CSS content when the document is loaded locally, see issue 618125@Connect.

  15. EricLaw [MSFT] says:

    @the_dees: By default, documents loaded "locally" aren't in IE9 browser mode. Hence, by-design.

  16. Tony Ross [MSFT] says:

    @jabcreations

    IE9's handling of XML errors complies with what is defined by the XML specification (see http://www.w3.org/…/REC-xml). How those errors are displayed is aimed at balancing end-user and developer requirements. Most end-users have no idea what an XML error is, nor can they do anything about it, so we chose to avoid confusing them with the error details. We also chose to present them with the content occuring before the point of failure so they would have some hope of getting at the information they were looking for. To continue to support developers, we moved the notification and details for XML parsing errors into the developer toolbar, which is more consistent with the notification model for other types of developer-oriented errors, such as those generated from script.

  17. EricLaw [MSFT] says:

    Tony posted a longer blog about the XHTML MIME type here: blogs.msdn.com/…/xhtml-in-ie9.aspx