Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions lib/private/Files/Filesystem.php
Original file line number Diff line number Diff line change
Expand Up @@ -390,17 +390,25 @@ public static function mount($class, $arguments, $mountpoint) {
}

/**
* check if the requested path is valid
* Validates a file path for safety in the Nextcloud virtual filesystem.
*
* @param string $path
* @return bool
* This method is the primary defense against directory traversal and
* path manipulation attacks. It ALWAYS normalizes the input (see {@see normalizePath}),
* converting slash and unicode variants to a canonical absolute path.
*
* After normalization, any path containing '/..' segments (traversal attempts) is rejected.
* Normalized paths like '//foo//bar' are allowed and become '/foo/bar'.
*
* @param string $path Untrusted or user-supplied path to check.
* @return bool True if the path is safe, false otherwise.
Comment on lines +395 to +403
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc string is longer than the implementation of the the function, it literally describes the implementation.
IMHO this is not a good thing because docs are not always kept up to date and will differ from implementation and then it just confuses at some point.
Better to just state the intent of the method and make the code itself self explaining.

*/
public static function isValidPath($path) {
public static function isValidPath(string $path): bool {
$path = self::normalizePath($path);
if (!$path || $path[0] !== '/') {
$path = '/' . $path;
}
if (str_contains($path, '/../') || strrchr($path, '/') === '/..') {

// Invariant: normalized path is non-empty and absolute.
assert($path !== '' && $path[0] === '/', 'normalizePath() must return absolute path');

if (str_contains($path, '/../') || str_ends_with($path, '/..')) {
return false;
}
return true;
Expand Down
1 change: 1 addition & 0 deletions tests/lib/Files/FilesystemTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ public function testNormalizePathKeepUnicodeCache(): void {
public static function isValidPathData(): array {
return [
['/', true],
['', true],
['/path', true],
['/foo/bar', true],
['/foo//bar/', true],
Expand Down
Loading