← CodeClarityLab Home
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 25
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings F 0 pings S 0 pings S 1 ping M 1 ping T 0 pings W 0 pings T 1 ping F 1 ping S 0 pings S 0 pings M 0 pings T 1 ping W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F
No pings yet today
No pings yesterday
Amazonbot 10 Perplexity 3 Unknown AI 3 Ahrefs 2 Google 2 Majestic 1
crawler 19 crawler_json 1 pre-tracking 1
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