diff --git a/system/Helpers/security_helper.php b/system/Helpers/security_helper.php index d42ac0dda777..d73fd6219b12 100644 --- a/system/Helpers/security_helper.php +++ b/system/Helpers/security_helper.php @@ -15,11 +15,69 @@ if (! function_exists('sanitize_filename')) { /** - * Sanitize a filename to use in a URI. + * Sanitize Filename + * + * Tries to sanitize filenames in order to prevent directory traversal attempts + * and other security threats, which is particularly useful for files that + * were supplied via user input. + * + * If it is acceptable for the user input to include relative paths, + * e.g. file/in/some/approved/folder.txt, you can set the second optional + * parameter, $relativePath to TRUE. + * + * @param string $filename Input file name + * @param bool $relativePath Whether to preserve paths */ - function sanitize_filename(string $filename): string + function sanitize_filename(string $filename, bool $relativePath = false): string { - return service('security')->sanitizeFilename($filename); + // List of sanitized filename strings + $bad = [ + '../', + '', + '<', + '>', + "'", + '"', + '&', + '$', + '#', + '{', + '}', + '[', + ']', + '=', + ';', + '?', + '%20', + '%22', + '%3c', + '%253c', + '%3e', + '%0e', + '%28', + '%29', + '%2528', + '%26', + '%24', + '%3f', + '%3b', + '%3d', + ]; + + if (! $relativePath) { + $bad[] = './'; + $bad[] = '/'; + } + + $filename = remove_invisible_characters($filename, false); + + do { + $old = $filename; + $filename = str_replace($bad, '', $filename); + } while ($old !== $filename); + + return stripslashes($filename); } } diff --git a/system/Security/Security.php b/system/Security/Security.php index 9e87a2177cda..aa744d9ed343 100644 --- a/system/Security/Security.php +++ b/system/Security/Security.php @@ -427,59 +427,16 @@ public function shouldRedirect(): bool * e.g. file/in/some/approved/folder.txt, you can set the second optional * parameter, $relativePath to TRUE. * + * @deprecated 4.6.2 Use `sanitize_filename()` instead + * * @param string $str Input file name * @param bool $relativePath Whether to preserve paths */ public function sanitizeFilename(string $str, bool $relativePath = false): string { - // List of sanitize filename strings - $bad = [ - '../', - '', - '<', - '>', - "'", - '"', - '&', - '$', - '#', - '{', - '}', - '[', - ']', - '=', - ';', - '?', - '%20', - '%22', - '%3c', - '%253c', - '%3e', - '%0e', - '%28', - '%29', - '%2528', - '%26', - '%24', - '%3f', - '%3b', - '%3d', - ]; - - if (! $relativePath) { - $bad[] = './'; - $bad[] = '/'; - } - - $str = remove_invisible_characters($str, false); - - do { - $old = $str; - $str = str_replace($bad, '', $str); - } while ($old !== $str); + helper('security'); - return stripslashes($str); + return sanitize_filename($str, $relativePath); } /** diff --git a/system/Security/SecurityInterface.php b/system/Security/SecurityInterface.php index 03a5ba2321d0..ebd8919cd109 100644 --- a/system/Security/SecurityInterface.php +++ b/system/Security/SecurityInterface.php @@ -66,6 +66,8 @@ public function shouldRedirect(): bool; * e.g. file/in/some/approved/folder.txt, you can set the second optional * parameter, $relativePath to TRUE. * + * @deprecated 4.6.2 Use `sanitize_filename()` instead + * * @param string $str Input file name * @param bool $relativePath Whether to preserve paths */ diff --git a/user_guide_src/source/changelogs/v4.6.2.rst b/user_guide_src/source/changelogs/v4.6.2.rst index dd988c4778b5..089fb01e1514 100644 --- a/user_guide_src/source/changelogs/v4.6.2.rst +++ b/user_guide_src/source/changelogs/v4.6.2.rst @@ -22,14 +22,21 @@ Message Changes Changes ******* +- **Security:** The ``sanitize_filename()`` function from the Security helper now supports a second parameter to control whether relative paths are allowed. + ************ Deprecations ************ +- **Security:** The ``Security::sanitizeFilename()`` method is deprecated. Use ``sanitize_filename()`` instead. +- **Security:** The ``SecurityInterface::sanitizeFilename()`` method is deprecated. + ********** Bugs Fixed ********** +- **Security:** Fixed a bug where the ``sanitize_filename()`` function from the Security helper would throw an error when used in CLI requests. + See the repo's `CHANGELOG.md `_ for a complete list of bugs fixed. diff --git a/user_guide_src/source/helpers/security_helper.rst b/user_guide_src/source/helpers/security_helper.rst index 500b7fd85b11..405a6e489051 100644 --- a/user_guide_src/source/helpers/security_helper.rst +++ b/user_guide_src/source/helpers/security_helper.rst @@ -20,15 +20,15 @@ Available Functions The following functions are available: -.. php:function:: sanitize_filename($filename) +.. php:function:: sanitize_filename($filename[, $relativePath = false]) :param string $filename: Filename + :param bool $relativePath: Whether the relative path is acceptable (available since v4.6.2) :returns: Sanitized file name :rtype: string Provides protection against directory traversal. - This function is an alias for ``\CodeIgniter\Security::sanitizeFilename()``. For more info, please see the :doc:`Security Library <../libraries/security>` documentation. diff --git a/user_guide_src/source/libraries/security.rst b/user_guide_src/source/libraries/security.rst index 07e2e8756d18..8fc49d646b1a 100644 --- a/user_guide_src/source/libraries/security.rst +++ b/user_guide_src/source/libraries/security.rst @@ -241,3 +241,5 @@ If it is acceptable for the user input to include relative paths, e.g., **file/i the second optional parameter, ``$relativePath`` to ``true``. .. literalinclude:: security/010.php + +This method is an alias for the ``sanitize_filename()`` function from the Security helper.