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

mime_content_type()

php PHP 5.3+ Intermediate
debt(d5/e3/b3/t9)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list semgrep and psalm as tools, and the code_pattern explicitly calls out '$_FILES["type"]' usage and extension-only checks. These are not default linter catches — they require configured SAST rules (semgrep patterns) or static analysis (psalm), placing this squarely at d5.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix states replacing client-supplied MIME with finfo_file() or mime_content_type() — a small, localised substitution in the upload-handling code. It's more than a one-liner because you need to also remove the $_FILES['type'] reliance and potentially add extension cross-checking, but it stays within a single component.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). The applies_to contexts are web and cli, but in practice this pattern is confined to file-upload handling logic. It doesn't spread across the whole codebase — only the upload validation component pays the tax. Future maintainers of upload code must be aware, but the rest of the codebase is unaffected.

t9 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'catastrophic trap' (t9). The misconception field is explicit: '$_FILES["type"] is sufficient for file validation' — a belief nearly every developer holds on first encounter because the field name suggests it is the file's MIME type. In reality it is fully attacker-controlled. The 'obvious' way (reading the provided MIME field) is always wrong for security purposes, matching the t9 anchor perfectly.

About DEBT scoring →

Also Known As

mime_content_type() MIME detection fileinfo extension

TL;DR

Detects the actual MIME type of a file by inspecting its content — not its extension or the browser-reported type.

Explanation

mime_content_type($filename) reads the file's binary content and determines its actual type using libmagic — the same library used by the Unix file command. This is critical for file upload validation because the browser-reported $_FILES['file']['type'] is completely attacker-controlled and cannot be trusted. Even extension checks can be bypassed with polyglot files. mime_content_type() on the actual tmp_name is the correct first step, combined with an allowlist of permitted MIME types.

Common Misconception

Checking MIME type via $_FILES['type'] is sufficient for file validation. $_FILES['type'] is supplied by the browser and trivially forged. Use the fileinfo extension (finfo_file()) which inspects the actual file bytes to determine the real MIME type.

Why It Matters

Trusting the MIME type from the HTTP request (Content-Type or file extension) is dangerous — the actual file content determines the real type. Server-side MIME detection prevents disguised malicious uploads.

Common Mistakes

  • Using $_FILES['file']['type'] for MIME validation — this is the browser-reported type, fully attacker-controlled.
  • Relying on the file extension alone — a PHP file named image.jpg is still PHP.
  • Not checking magic bytes (file signature) for the most sensitive upload types.
  • mime_content_type() being disabled in some hosting environments — use finfo_file() as the preferred alternative.

Code Examples

✗ Vulnerable
// Trusting browser-supplied MIME type:
$type = $_FILES['upload']['type']; // Attacker-controlled!
if (in_array($type, ['image/jpeg', 'image/png'])) {
    move_uploaded_file($_FILES['upload']['tmp_name'], $dest);
}

// Safe server-side check:
$finfo = new finfo(FILEINFO_MIME_TYPE);
$type = $finfo->file($_FILES['upload']['tmp_name']);
✓ Fixed
// Detect MIME from file magic bytes — not browser Content-Type header
\$finfo = new \finfo(FILEINFO_MIME_TYPE);
\$mime  = \$finfo->file(\$_FILES['upload']['tmp_name']);
// Returns: 'image/jpeg', 'application/pdf', 'text/plain', etc.

// mime_content_type() is an older alternative — same underlying libmagic
\$mime = mime_content_type(\$_FILES['upload']['tmp_name']);

// Allowlist check:
\$allowed = ['image/jpeg', 'image/png', 'image/webp', 'application/pdf'];
if (!in_array(\$mime, \$allowed, true)) abort(415, 'Unsupported Media Type');

Added 15 Mar 2026
Edited 22 Mar 2026
Views 23
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 1 ping W 0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 1 ping W 0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F
No pings yet today
No pings yesterday
Amazonbot 7 Perplexity 4 Ahrefs 2 Unknown AI 2 SEMrush 2 Google 1
crawler 17 pre-tracking 1
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Low
⚡ Quick Fix
Use finfo_file() or mime_content_type() to detect the actual MIME type from file content — never trust the client-supplied MIME type or file extension alone for security decisions
📦 Applies To
PHP 5.3+ web cli
🔗 Prerequisites
🔍 Detection Hints
File type check using $_FILES['type'] (client-supplied); extension-only check without content inspection; mime_content_type() without also checking extension
Auto-detectable: ✓ Yes semgrep psalm
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Medium ✗ Manual fix Fix: Medium Context: Function Tests: Update
CWE-434 CWE-430

✓ schema.org compliant