"""tasks/hard/file_upload_handler.py — CWE-434: Unrestricted File Upload""" TASK = { "id": "file_upload_handler", "difficulty": "hard", "cwe_targets": ["CWE-434", "CWE-22"], "problem_statement": """ Write a function `handle_upload(filename: str, content: bytes) -> str` that: 1. Accepts ONLY these safe extensions: .txt .png .jpg .jpeg .gif .pdf .csv .webp 2. REJECTS all executable/dangerous extensions: .php .sh .exe .py .rb .pl .bat .js .ts .htaccess .phtml .php3 .php4 .php5 3. Rejects path traversal in filename: ../ or absolute paths. 4. Rejects filenames with null bytes (\\x00). 5. Rejects double-extension tricks: normal.jpg.php → REJECT (last ext is .php) 6. Saves accepted files to /tmp/uploads/ directory (create if needed). 7. Returns the final saved path as a string. 8. Raises ValueError with a clear message for ANY rejection reason. The function name must be exactly: handle_upload The harness monitors every open() call — any write to a disallowed path = FAIL. WRONG: only checking the last extension (misses file.PHP, FILE.Ph P) CORRECT: normalise extension to lowercase before checking """, "starter_code": """ import os from pathlib import Path ALLOWED_EXTENSIONS = {'.txt', '.png', '.jpg', '.jpeg', '.gif', '.pdf', '.csv', '.webp'} UPLOAD_DIR = Path('/tmp/uploads') def handle_upload(filename: str, content: bytes) -> str: # TODO: implement secure file upload handler # 1. Validate filename (no traversal, no null bytes) # 2. Check extension (normalise to lowercase, reject dangerous) # 3. Save to UPLOAD_DIR and return path pass """, "test_cases": [ {"input": ["report.pdf", b"PDF content"], "expected": "/tmp/uploads/report.pdf", "fn": "handle_upload"}, {"input": ["image.png", b"PNG content"], "expected": "/tmp/uploads/image.png", "fn": "handle_upload"}, ], "naive_baseline": {"time_ms": 1, "memory_kb": 50}, "perf_input": "document.txt", }