MIME Types and Browser Security: Sniffing, nosniff, CSP, and CORS
Browsers enforce MIME types as part of their security model. Content-Type headers are not just metadata about file format; they control how browsers parse, execute, and sandbox content. When a server sends the wrong MIME type, browsers make security-relevant decisions about whether to execute scripts, render markup, or apply cross-origin restrictions. MIME sniffing, where the browser detects the actual content type from the file's bytes rather than the declared header, was introduced to handle misconfigured servers but creates attack vectors.1 X-Content-Type-Options: nosniff closes this gap by instructing browsers to trust the declared type exactly.2 Strict CSP configurations check MIME type before executing scripts, adding a second enforcement layer beyond the URL allowlist. Cross-origin resources like fonts and images loaded by canvas require CORS headers that interact with MIME type expectations. Understanding these interactions is fundamental to hardening a web application against content-type confusion attacks.
What MIME sniffing is and when browsers activate it
MIME sniffing is the process by which a browser inspects the first bytes of a response body to determine the actual content type, overriding or supplementing the declared Content-Type header. The WHATWG MIME Sniffing Standard defines the exact sniffing algorithm.3 Browsers activate sniffing primarily when the server sends no Content-Type header, when the Content-Type is text/plain for a resource loaded in a context that expects a specific type, or when the browser detects executable content in a response declared as a safe type.
Content-type confusion attacks
The security risk is a content-type confusion attack: an attacker uploads a file that appears to be an image (and passes server-side format validation) but contains an HTML or script payload that the browser detects and executes when sniffing is active.4 Furthermore, older Internet Explorer versions were particularly aggressive sniffers, treating any response as HTML if the content began with HTML-like bytes.
X-Content-Type-Options: nosniff mechanics
The X-Content-Type-Options: nosniff response header instructs the browser to use the declared Content-Type value exactly and not perform sniffing. When nosniff is present, the browser refuses to execute a script served as text/plain, refuses to render a stylesheet served as application/octet-stream, and refuses to treat any response as HTML unless the Content-Type declares it as such. Modern browsers apply nosniff to all resource types; older browsers applied it only to scripts and stylesheets.5
Why nosniff requires correct MIME types first
Consequently, setting nosniff on every response is best practice rather than applying it selectively. Building on this, nosniff works correctly only when combined with accurate MIME types. Setting nosniff on a server that sends wrong types for images or scripts will cause browsers to reject those resources outright instead of attempting to sniff the correct format from the response body. Fix MIME types first, then enable nosniff globally so that the browser's strict trust in your declared types actually helps rather than hurts your users.
Cross-origin resource MIME rules for fonts and images
Browsers apply CORS enforcement to certain resource types loaded cross-origin. Fonts are the most important example: any font loaded from a different origin requires an Access-Control-Allow-Origin header from the font server, regardless of the MIME type.6 The failure is silent and there is no console error. For images, CORS enforcement applies specifically to canvas operations: drawing a cross-origin image onto a canvas taints it unless the image server sends Access-Control-Allow-Origin and the img element carries crossorigin="anonymous". MIME type plays a secondary role in this: an incorrectly typed cross-origin font still fails even if CORS is configured, because the browser must also recognise the MIME type as a font format. Furthermore, CSP's font-src directive controls from which origins fonts may be loaded, adding a third layer of restriction on top of CORS and MIME type validation.
Subresource Integrity and its relationship with MIME type enforcement
Subresource Integrity (SRI) adds a cryptographic hash check to external script and stylesheet elements. When an element carries an integrity attribute containing a base64-encoded hash, the browser downloads the resource, computes the hash against the received bytes, and compares it to the declared value before executing or applying the resource. A mismatch causes the browser to block the resource entirely. SRI requires CORS on the resource server: the response must include Access-Control-Allow-Origin for the browser to share the response body with the integrity checking algorithm.7
MIME type enforcement and SRI operate as independent checks applied in sequence. A script must carry a valid JavaScript MIME type and pass the integrity hash check before the browser executes it. Serving an SRI-protected script with text/plain fails the MIME type check first, and the browser blocks the resource before computing the hash at all. Consequently, fixing the MIME type is a prerequisite before SRI integrity errors become meaningful.
require-sri-for and layered script security
The CSP require-sri-for directive (available in some browsers) enforces that all scripts and styles in the document carry SRI integrity attributes, blocking any script or stylesheet that lacks a valid hash regardless of its origin or MIME type. Combining require-sri-for with a script-src allowlist and X-Content-Type-Options: nosniff creates three independent enforcement layers: only approved origins, only verified content hashes, and only correct MIME types. Implementing all three layers means an attacker must compromise the origin, match the expected hash, and serve the correct MIME type simultaneously, which raises the difficulty of a successful content injection attack dramatically.
Generating SRI hashes for your build pipeline
Generating SRI hashes during the build step ensures every deployed script and stylesheet carries an integrity attribute that matches the exact bytes the browser will receive. The openssl dgst command computes a SHA-384 hash of a file and the base64 utility encodes it for the integrity attribute value.7 Build tools like webpack-subresource-integrity automate this process by computing hashes at bundle time and injecting the integrity and crossorigin attributes into the generated HTML, removing the manual step entirely.8
Hashing at build time also means the integrity value stays in sync with the exact bytes the browser receives, so a minification change that alters the file automatically produces a new hash without manual intervention. This prevents the stale-hash problem where a code update ships new script bytes but an old integrity attribute blocks them. pair the script Content-Type with SRI so the MIME check and the hash check pass together.
When to use this
Use this guide when hardening a web application against content-type confusion attacks, auditing response headers for security posture, or diagnosing silent resource failures caused by CORS or MIME type mismatches.
Examples
Add X-Content-Type-Options: nosniff globally in Nginx
Place in the http {} block to apply to all responses. Combined with correct MIME types, this prevents content-type confusion attacks.
Verify nosniff and Content-Type with curl
Check both the Content-Type and X-Content-Type-Options headers together to confirm both are correct.
CSP script-src with MIME type enforcement
Strict CSP rejects scripts served with incorrect MIME types. Setting the correct type and CSP together prevents both sniffing and unlisted script execution.
- 1.
Mozilla Developer Network, "MIME type verification," developer.mozilla.org, accessed June 2026. https://developer.mozilla.org/en-US/docs/Web/Security/Practical_implementation_guides/MIME_types
- 2.
OWASP Foundation, "HTTP Headers Cheat Sheet," owasp.org, 2024. https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html
- 3.
Adam Barth and Ian Hickson, "Media Type Sniffing," draft-ietf-websec-mime-sniff-03, IETF, May 2011. https://datatracker.ietf.org/doc/html/draft-ietf-websec-mime-sniff-03
- 4.
MITRE, "CAPEC-209: XSS Using MIME Type Mismatch," capec.mitre.org, accessed June 2026. https://capec.mitre.org/data/definitions/209.html
- 5.
Mozilla Developer Network, "X-Content-Type-Options header," developer.mozilla.org, accessed June 2026. https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Content-Type-Options
- 6.
W3C, "CSS Fonts Module Level 3," w3.org, 2018. https://www.w3.org/TR/2018/REC-css-fonts-3-20180920/
- 7.
W3C, "Subresource Integrity," w3.org, 2016. https://www.w3.org/TR/2016/REC-SRI-20160623/
- 8.
"webpack-subresource-integrity," GitHub, github.com, accessed June 2026. https://github.com/waysact/webpack-subresource-integrity