Note
web
python
mime-confusion
file-upload
content-type
xss
Control the served Content-Type by storing a filename whose URL-like suffix changes the guessed MIME.
mimetypes.guess_type() Confused by Pseudo-URL Filenames
mimetypes.guess_type() is not a content detector — it infers type from the string and historically
treats it with URL-like semantics. Query-string-looking suffixes can change the guessed MIME, so the
app serves disk bytes as whatever the name implies, even when the extension or content says otherwise.
Why It Works
- Security logic assumes "if MIME starts with
image/, browser execution risk is gone" — but the MIME came from a manipulable filename.
Vulnerable Pattern
- Upload/move endpoints where the attacker controls the stored filename, and the download route sets
Content-Typefrommimetypes.guess_type(filename)rather than content or a fixed allowlist.
Exploit Flow
- Test whether the route preserves unusual filenames containing
?,%3f, fragments, or multi-extension forms. - Verify both what the server stores on disk and what MIME the download route emits.
- Align the served MIME with the browser sink you need — a script include, an SVG load, a JSON fetch.
Variations
test.js?image.svg,foo.html?.png,bar.svg#x.js— depending on which parser runs at each step.
Common Blockers
- The filesystem path may strip or reject
?, or the download route may canonicalize names before MIME guessing.
PoC Sketch
curl -F 'file=@poc.js;filename=test.js?image.svg' https://target/api/upload
Good Situations To Use It
- An upload route lets you keep odd characters in the stored name.
- The download route derives
Content-Typefrom the name viaguess_type. - You need a specific MIME to reach a browser sink.
Sources
breizhctf2026/web/no_thanks_i_use_ai