From 753dd4486ecda108fcad49604e17ea5e8dd046e3 Mon Sep 17 00:00:00 2001 From: michalsn Date: Wed, 12 Aug 2026 08:10:06 +0200 Subject: [PATCH] docs: warn against untrusted paths in UploadedFile move()/store() --- system/HTTP/Files/UploadedFile.php | 10 +++++++--- user_guide_src/source/libraries/uploaded_files.rst | 10 ++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/system/HTTP/Files/UploadedFile.php b/system/HTTP/Files/UploadedFile.php index 95a393616dff..be2b74c2025c 100644 --- a/system/HTTP/Files/UploadedFile.php +++ b/system/HTTP/Files/UploadedFile.php @@ -122,7 +122,9 @@ public function __construct(string $path, string $originalName, ?string $mimeTyp * @see http://php.net/is_uploaded_file * @see http://php.net/move_uploaded_file * - * @param string $targetPath Path to which to move the uploaded file. + * @param string $targetPath Path to which to move the uploaded file. This is NOT sanitized. Never build it from + * untrusted input: a value containing "../" can move the file outside the intended + * directory. Use a path controlled by your application. * @param string|null $name The name to rename the file to. When null, the client-provided name is used and sanitized. * A caller-supplied name is NOT sanitized. * @param bool $overwrite State for indicating whether to overwrite the previously generated file with the same @@ -347,8 +349,10 @@ public function isValid(): bool * By default, upload files are saved in writable/uploads directory. The YYYYMMDD folder * and random file name will be created. * - * @param string|null $folderName the folder name to writable/uploads directory. - * @param string|null $fileName the name to rename the file to. + * @param string|null $folderName the folder name to writable/uploads directory. This is NOT sanitized. Never build + * it from untrusted input: a value containing "../" can move the file outside the + * uploads directory. + * @param string|null $fileName the name to rename the file to. A caller-supplied name is NOT sanitized. * * @return string file full path */ diff --git a/user_guide_src/source/libraries/uploaded_files.rst b/user_guide_src/source/libraries/uploaded_files.rst index eadc1d8ef2e9..beaadd8687af 100644 --- a/user_guide_src/source/libraries/uploaded_files.rst +++ b/user_guide_src/source/libraries/uploaded_files.rst @@ -331,6 +331,16 @@ In PHP versions below 8.1, this returns ``null`` Moving Files ============ +.. warning:: + Do not let user input directly decide the destination directory. The ``$targetPath`` argument of ``move()`` and the + ``$folderName`` argument of ``store()`` are never sanitized, so an attacker-controlled value containing ``../`` can + move the uploaded file outside the intended directory. Use directories controlled by your application. + + Filenames are only sanitized by default: ``move()`` sanitizes the client-provided name when the ``$name`` argument is + omitted, and ``store()`` generates a random name when ``$fileName`` is omitted. A caller-supplied ``$name`` or + ``$fileName`` is NOT sanitized, so if you pass one, generate it yourself or sanitize it with + :php:func:`sanitize_filename`. + with Original Filename ----------------------