# Content-Type substring sniffing bypass

Clients matching MIME by substring or ignoring nosniff, letting uploaded files execute

_Area: Web infrastructure and server-side requests. Seen in 3 disclosed reports; one confirmed bounty: $3,000; latest 2023-03-28. Updated 2026-11-02._

## How it works
A client decides how to handle a file by looking at its Content-Type. The safe assumption is that the type is matched exactly and that `X-Content-Type-Options: nosniff` stops the client from guessing. The weakness is that some clients match the MIME string by substring search over the whole header value, or ignore nosniff entirely. If any part of the header is attacker-influenced (a reflected parameter, a filename, a charset), the magic string can be smuggled in and the file is treated as an executable type even though the real type is something harmless like an image [E2](https://bugbountylibrary.com/r/h1%3A78158.md).

## Where it shows up
- Server code that builds Content-Type from user input: `lang`, `charset`, `encoding`, `filename` parameters reflected into the header [E2](https://bugbountylibrary.com/r/h1%3A78158.md).
- Upload endpoints that store attacker files and serve them back with a header the attacker can nudge.
- Clients or plugins that use `indexOf`/`contains` on the Content-Type instead of an exact match [E2](https://bugbountylibrary.com/r/h1%3A78158.md).
- Responses missing `X-Content-Type-Options: nosniff`, or where nosniff is present but the client still sniffs [E2](https://bugbountylibrary.com/r/h1%3A78158.md).
- JSONP endpoints and reflected parameters that echo into headers.

## How to review
The invariant: the effective MIME type must be derived from an exact, server-controlled value, and the client must honor nosniff. Check that Content-Type is never assembled from request parameters; that any reflected parameter cannot inject a MIME token; and that the consuming client compares the type exactly rather than by substring. For each upload path, ask: can the attacker influence any byte of the Content-Type header, and does the client require the magic string to be the whole type? If the answer is no to the first and yes to the second, it is safe.

## How finders spotted it
- Reversed the Rosetta Flash mitigation, noticed Flash uses indexOf-style search over the whole Content-Type value, hypothesized any header containing the magic string would trigger execution, then tested with uploaded images and JSONP endpoints [E2](https://bugbountylibrary.com/r/h1%3A78158.md).

## Variants seen
- Substring MIME match in Flash Player, bypassing nosniff and the Rosetta Flash alphanumeric patch [E2](https://bugbountylibrary.com/r/h1%3A78158.md).

## Impact and severity
In the evidence this restored a SOP bypass via JSONP endpoints and allowed attacker-uploaded files to execute as Flash, defeating a prior mitigation [E2](https://bugbountylibrary.com/r/h1%3A78158.md). Severity is raised when the sniffing bypass chains with a JSONP/SOP technique, because it reopens cross-origin data theft that the patch was meant to close [E2](https://bugbountylibrary.com/r/h1%3A78158.md).

## Seen in real software
Open-source packages and projects, and products, where this pattern was found. If the target runs one, compare the version it runs with the fix.
- **Electron** (command_line_args.cc) v1.7.11, v1.6.16 and v1.8.2-beta4, fixed in v2.0.1, v1.8.7, and v1.7.15: Electron Windows Protocol Handler MITM/RCE (bypass for CVE-2018-1000006 fix). Report: https://bugbountylibrary.com/r/blog%3Ablog-doyensec-com-2018-05-24-electron-win-protocol-handler-bug-bypass-html.md

## Evidence
- E1: https://bugbountylibrary.com/r/blog%3Ablog-doyensec-com-2018-05-24-electron-win-protocol-handler-bug-bypass-html.md
- E2: https://bugbountylibrary.com/r/h1%3A78158.md
- E3: https://bugbountylibrary.com/r/blog%3Aportswigger-net-research-the-curl-quirk-that-exposed-burp-suite-amp-google-chrome.md
