T09 · Insecure Skill Coding Practices
- Location
references/class-examples.md:691- Finding
Untrusted Upload Filenames Allow Path Traversal and Arbitrary File Writes
- Content
View full analysis
getValue('username'); $file = $form->getFile('avatar'); if ($file !== null) { \Amp\File\write('/uploads/' . $file->getFilename(), $file->getContents()); } return new Response(HttpStatus::OK, [], "Hello, $username"); } } ``` ```php class StreamingUploadHandler implements RequestHandler { public function handleRequest(Request $request): Response { $parser = new StreamingFormParser(); $parser->parseForm($request, function (mixed $field) { if ($field instanceof FileField) { $dest = File\openFile('/uploads/' . $field->getFilename(), 'w'); ByteStream\pipe($field->getStream(), $dest); } }); return new Response(HttpStatus::OK, [], 'Uploaded'); } } ``` ### Technical Analysis Both examples use the client-supplied multipart filename directly when constructing a destination path. Multipart filenames are attacker-controlled and may contain traversal sequences such as `../`, platform-specific separators, absolute path components, or names of existing files. Concatenating such a filename with `/uploads/` does not guarantee that the resulting normalized path remains inside the intended upload directory. Opening the destination with write mode may also truncate an existing file. The examples do not: - Remove directory components from the supplied filename. - Generate a server-controlled filename. - Resolve and validate the canonical destination path. ...[truncated 1683 chars]- Remediation
View remediation
getStream(), $dest); ``` The implementation should additionally verify that `$uploadRoot` is the intended canonical directory and that `validatedExtension()` uses a strict application-specific allowlist. ]]>
