unrestricted-file-upload-anti-pattern
Security anti-pattern for unrestricted file upload vulnerabilities (CWE-434). Use when generating or reviewing code that handles file uploads, processes user-submitted files, or stores uploaded content. Detects missing extension, MIME type, and size validation.
What this skill does
# Unrestricted File Upload Anti-Pattern
**Severity:** Critical
## Summary
Applications accept user-uploaded files without validating type, content, or size, enabling attackers to upload malicious scripts or executables. Leads to remote code execution (web shells), server compromise, or denial-of-service (disk exhaustion).
## The Anti-Pattern
The anti-pattern is accepting uploaded files without validating type, content, and size.
### BAD Code Example
```python
# VULNERABLE: No validation of file type, content, or size.
from flask import Flask, request
import os
UPLOAD_FOLDER = '/var/www/uploads' # This directory might be accessible by the web server.
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
@app.route('/upload', methods=['POST'])
def upload_file():
if 'file' not in request.files:
return 'No file part', 400
file = request.files['file']
if file.filename == '':
return 'No selected file', 400
# CRITICAL FLAW: The application takes the filename as is and saves the file.
# An attacker can upload a file named `shell.php` with PHP code.
# If the `UPLOAD_FOLDER` is web-accessible and PHP is executed,
# the attacker achieves Remote Code Execution.
filename = file.filename
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return f'File {filename} uploaded successfully', 200
# Attack Scenario:
# 1. Attacker crafts a PHP file named `shell.php` containing `<?php system($_GET['cmd']); ?>`.
# 2. Attacker uploads `shell.php` via this endpoint.
# 3. Attacker accesses `http://your-app.com/uploads/shell.php?cmd=ls%20-la`
# and can now execute arbitrary commands on the server.
```
### GOOD Code Example
```python
# SECURE: Implement a multi-layered validation approach for file uploads.
from flask import Flask, request, jsonify
import os
import uuid # For generating unique filenames
from magic import from_buffer # `python-magic` for magic byte detection
UPLOAD_FOLDER = '/var/www/safe_uploads' # Store files outside the web root.
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'pdf'}
MAX_FILE_SIZE = 5 * 1024 * 1024 # 5 MB
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/upload/secure', methods=['POST'])
def upload_file_secure():
if 'file' not in request.files:
return jsonify({'error': 'No file part'}), 400
file = request.files['file']
if file.filename == '':
return jsonify({'error': 'No selected file'}), 400
if file:
# 1. Validate file extension (allowlist approach).
if not allowed_file(file.filename):
return jsonify({'error': 'File type not allowed'}), 400
# 2. Validate file size.
file.seek(0, os.SEEK_END)
file_length = file.tell()
file.seek(0)
if file_length > MAX_FILE_SIZE:
return jsonify({'error': 'File too large'}), 400
# 3. Validate actual MIME type using magic bytes (more reliable than Content-Type header).
file_buffer = file.read(1024) # Read a chunk for magic byte detection
file.seek(0) # Reset file pointer
actual_mime = from_buffer(file_buffer, mime=True)
if actual_mime not in ['image/png', 'image/jpeg', 'image/gif', 'application/pdf']:
return jsonify({'error': f'Invalid file content type: {actual_mime}'}), 400
# 4. Generate a unique and safe filename. Never use the original filename directly.
original_extension = file.filename.rsplit('.', 1)[1].lower()
safe_filename = str(uuid.uuid4()) + '.' + original_extension
# 5. Store the file in a secure location, preferably outside the web root.
file.save(os.path.join(app.config['UPLOAD_FOLDER'], safe_filename))
return jsonify({'message': f'File {safe_filename} uploaded successfully'}), 200
```
## Detection
- **Review file upload handlers:** Identify all endpoints that allow users to upload files.
- **Check validation logic:** Examine how filenames, file types, and file contents are validated. Look for:
- Missing extension checks or using blocklists instead of allowlists.
- Relying solely on the `Content-Type` HTTP header, which is easily spoofed.
- Not checking the actual content of the file (magic bytes).
- Missing size limits.
- **Inspect storage location:** Determine where uploaded files are stored. Are they in a web-accessible directory? Can executables be run from there?
## Prevention
- [ ] **Strict allowlist for file extensions:** Allow only specific safe extensions (`.png`, `.jpg`, `.pdf`). Never use blocklists.
- [ ] **Verify file content (magic bytes):** Inspect first bytes to determine true file type. Never trust client-provided `Content-Type` header.
- [ ] **Enforce file size limits:** Set maximum file size to prevent DoS and resource exhaustion.
- [ ] **Generate unique, random filenames:** Use cryptographically secure random filenames. Never use user-provided filenames (prevents path traversal and overwrites).
- [ ] **Store files outside web root:** Store uploads in non-web-accessible directories. Serve through controlled handlers.
- [ ] **Set no-execute permissions:** Configure upload directory with no-execute permissions to block web shell execution.
- [ ] **Scan for malware:** Integrate antivirus/malware scanner for all uploads.
## Related Security Patterns & Anti-Patterns
- [Path Traversal Anti-Pattern](../path-traversal/): Attackers can try to use directory traversal sequences (`../`) in the filename to write files to unintended locations.
- [Command Injection Anti-Pattern](../command-injection/): If an uploaded file is later processed by a system command, it can lead to command injection.
- [Cross-Site Scripting (XSS) Anti-Pattern](../xss/): Malicious HTML or SVG files can be uploaded to perform XSS attacks.
## References
- [OWASP Top 10 A06:2025 - Insecure Design](https://owasp.org/Top10/2025/A06_2025-Insecure_Design/)
- [OWASP GenAI LLM10:2025 - Unbounded Consumption](https://genai.owasp.org/llmrisk/llm10-unbounded-consumption/)
- [OWASP API Security API4:2023 - Unrestricted Resource Consumption](https://owasp.org/API-Security/editions/2023/en/0xa4-unrestricted-resource-consumption/)
- [OWASP File Upload Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html)
- [CWE-434: Unrestricted Upload of File with Dangerous Type](https://cwe.mitre.org/data/definitions/434.html)
- [CAPEC-1: Accessing Functionality Not Properly Constrained by ACLs](https://capec.mitre.org/data/definitions/1.html)
- [PortSwigger: File Upload](https://portswigger.net/web-security/file-upload)
- Source: [sec-context](https://github.com/Arcanum-Sec/sec-context)
Related in Security
mac-ops
IncludedComprehensive macOS workstation operations — diagnose kernel panics, identify failing drives, audit launchd startup items, decode wake reasons, triage TCC permission denials, manage APFS snapshots, recover from no-boot. Use for: Mac is slow, slow bootup, won't boot, kernel panic, kernel_task hot, mds_stores CPU, photoanalysisd, cloudd, login loop, gray screen, sleep wake failure, drive failing, IO errors, APFS snapshots eating space, Time Machine local snapshots, Spotlight indexing, launchd, LaunchAgent, LaunchDaemon, login items, TCC permissions, Full Disk Access, Screen Recording denied, Gatekeeper, quarantine, com.apple.quarantine, app is damaged, helper tool, /Library/PrivilegedHelperTools, pmset, wake reasons, dark wake, sysdiagnose, panic.ips, DiagnosticReports, configuration profile, MDM profile, remote diagnostics over SSH.
a11y-audit
IncludedRun accessibility audits on web projects combining automated scanning (axe-core, Lighthouse) with WCAG 2.1 AA compliance mapping, manual check guidance, and structured reporting. Output is configurable: markdown report only, markdown plus machine-readable JSON, or markdown plus issue tracker integration. Use this skill whenever the user mentions "accessibility audit", "a11y audit", "WCAG audit", "accessibility check", "compliance scan", or asks to check a web project for accessibility issues. Also trigger when the user wants to verify WCAG conformance or map findings to a specific standard (CAN-ASC-6.2, EN 301 549, ADA/AODA).
erpclaw
IncludedAI-native ERP system with self-extending OS. Full accounting, invoicing, inventory, purchasing, tax, billing, HR, payroll, advanced accounting (ASC 606/842, intercompany, consolidation), and financial reporting. 413 actions across 14 domains, 43 expansion modules. Constitutional guardrails, adversarial audit, schema migration. Double-entry GL, immutable audit trail, US GAAP.
assess
IncludedAssesses and rates quality 0-10 across multiple dimensions (correctness, maintainability, security, performance, testability, simplicity) with pros/cons analysis. Compares against project conventions and prior decisions from memory. Produces structured evaluation reports with actionable improvement suggestions. Use when evaluating code, designs, architectures, or comparing alternative approaches.
spring-boot-security-jwt
IncludedProvides JWT authentication and authorization patterns for Spring Boot 3.5.x covering token generation with JJWT, Bearer/cookie authentication, database/OAuth2 integration, and RBAC/permission-based access control using Spring Security 6.x. Use when implementing authentication or authorization in Spring Boot applications.
code-hardcode-audit
IncludedDetect hardcoded values, magic numbers, and leaked secrets. TRIGGERS - hardcode audit, magic numbers, PLR2004, secret scanning.