diff --git a/Tests/InputFilterTest.php b/Tests/InputFilterTest.php index cda40c01..c003af12 100644 --- a/Tests/InputFilterTest.php +++ b/Tests/InputFilterTest.php @@ -508,6 +508,30 @@ public static function casesGeneric(): array 'C:\Documents\Newsletters\tmp', 'From generic cases', ], + 'path with parent traversal segment' => [ + 'path', + 'uploads/../config.php', + '', + 'From generic cases', + ], + 'path with leading parent traversal' => [ + 'path', + '../secret', + '', + 'From generic cases', + ], + 'path with trailing parent traversal' => [ + 'path', + 'uploads/..', + '', + 'From generic cases', + ], + 'filename containing dots is kept' => [ + 'path', + 'archive/backup..2018/file.txt', + 'archive/backup..2018/file.txt', + 'From generic cases', + ], 'user_01' => [ 'username', '&r%e\'d', diff --git a/src/InputFilter.php b/src/InputFilter.php index f8aedf61..f2395d2b 100644 --- a/src/InputFilter.php +++ b/src/InputFilter.php @@ -906,6 +906,12 @@ private function cleanHtml($source) */ private function cleanPath($source) { + // Reject any parent-directory (`..`) segment. The patterns below otherwise let a + // single `..` through on Linux-style paths (e.g. images/../config.php). + if (preg_match('#(?:^|[\\\\/])\.\.(?:[\\\\/]|$)#', $source)) { + return ''; + } + $linuxPattern = '/^[A-Za-z0-9_\/-]+[A-Za-z0-9_\.-]*([\\\\\/]+[A-Za-z0-9_-]+[A-Za-z0-9_\.-]*)*$/'; if (preg_match($linuxPattern, $source)) {