← Home ← Codex ← DEBT ← Engine
Browse by Category
+ added · updated 7d
← Back to glossary

File API — FileReader & File Input

JavaScript ES2015 Intermediate
debt(d7/e3/b3/t7)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). The detection_hints indicate automated detection is 'no' and the tool listed is semgrep, which requires a custom rule pattern to catch 'File.type used for security validation without server-side re-validation.' This is a specialist/custom pattern, not a default lint rule, and the misuse (trusting client-side MIME) is silent in production until an attacker exploits it — but a careful code reviewer could spot it, placing it at d7 rather than d9.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix specifies two concrete changes: swap FileReader for URL.createObjectURL() for image previews (one-call swap) and add finfo_file() server-side validation. This touches the JS client code and the PHP upload handler — two files but a straightforward, localised pattern replacement rather than a broad refactor.

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

Closest to 'localised tax' (b3). The applies_to scope is web contexts only and the concern is scoped to file upload handling logic. The misconception creates a security gap but it doesn't structurally infect unrelated parts of the codebase — only the upload component and its PHP counterpart pay the tax.

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

Closest to 'serious trap' (t7). The misconception field is explicit: File.type appears to validate MIME type but actually reads the browser's guess based on file extension, which is easily spoofed. A competent developer familiar with server-side MIME validation would reasonably trust File.type as analogous — but it contradicts expectations by being purely extension-based, making security-critical reliance on it a serious and non-obvious mistake.

About DEBT scoring →

Also Known As

FileReader File API file upload JS client-side file handling

TL;DR

File and FileReader provide client-side access to user-selected files before upload to PHP — enabling preview, validation, and chunked upload.

Explanation

input[type=file].files returns a FileList of File objects (extends Blob). FileReader.readAsDataURL() for image preview; readAsArrayBuffer() for binary processing; readAsText() for CSV/text. File.size, File.type, File.name for client-side validation before sending to PHP. Drag-and-drop: DataTransfer.files. Large files: split into chunks with File.slice() and upload sequentially via fetch to PHP. PHP receives the same $_FILES as a normal form upload.

Common Misconception

Client-side file type validation via File.type is sufficient — File.type reads the browser's MIME type guess based on file extension, which is easily spoofed; always validate MIME type server-side with PHP's finfo_file().

Why It Matters

Client-side file validation improves UX by rejecting invalid files instantly without a server round-trip, but PHP must re-validate everything — the client-side check is for usability not security.

Common Mistakes

  • Trusting File.type for security — it's based on extension, spoofable
  • Not checking file size before upload to avoid wasted bandwidth
  • Using FileReader for images when URL.createObjectURL() is more efficient

Code Examples

✗ Vulnerable
// FileReader for preview — inefficient, and trusts File.type:
if (file.type !== 'image/jpeg') throw new Error('Not a JPEG'); // spoofable
const reader = new FileReader();
reader.readAsDataURL(file); // loads entire file into memory
✓ Fixed
// Size validation client-side:
if (file.size > 10 * 1024 * 1024) throw new Error('File too large (max 10MB)');

// Efficient preview with object URL (no FileReader needed):
const preview = document.querySelector('#preview');
preview.src = URL.createObjectURL(file);
preview.onload = () => URL.revokeObjectURL(preview.src); // free memory

// PHP must re-validate:
// $finfo = new finfo(FILEINFO_MIME_TYPE);
// $mime = $finfo->file($_FILES['photo']['tmp_name']);

Added 17 Mar 2026
Edited 22 Mar 2026
Views 115
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 1 ping S 0 pings M 0 pings T 1 ping W 0 pings T 1 ping F 1 ping S 1 ping S 1 ping M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 1 ping M 1 ping T 0 pings W 0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 1 ping T 1 ping W 0 pings T
No pings yet today
Ahrefs 1
Amazonbot 13 Ahrefs 9 PetalBot 8 SEMrush 7 Unknown AI 5 Bing 5 Scrapy 5 Google 4 Perplexity 3 Twitter/X 3 Brave Search 2 Applebot 2 Majestic 1 Claude 1 Meta AI 1
crawler 66 crawler_json 2 pre-tracking 1
🧱 FUNDAMENTALS — new to this? Start with the ground floor.
JavaScript javascript The programming language of the browser — it reads and modifies the page (the DOM), reacts to user events, and fetches data without reloading.

JavaScript is the only language browsers execute, so every interactive behaviour on the web goes through it. Its two defining traits — single-threaded event loop and loose typing (== coercion) — explain the majority of both its bugs and its design patterns.

💡 Default to const, use === always, and reach for let only when a value genuinely reassigns.

Ask Codex about JavaScript →
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Medium
⚡ Quick Fix
Use URL.createObjectURL() for image preview (more efficient than FileReader); validate type and size client-side for UX but always re-validate in PHP with finfo_file()
📦 Applies To
javascript ES2015 web
🔗 Prerequisites
🔍 Detection Hints
File.type used for security validation without server-side finfo re-validation; no client-side file size check before upload
Auto-detectable: ✗ No semgrep
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: Function Tests: Update
CWE-434


✓ schema.org compliant