-Validate user input before using it to construct a file path, either using an off-the-shelf library
-like the sanitize-filename npm package, or by performing custom validation.
+Validate user input before using it to construct a file path.
-Ideally, follow these rules: +The choice of validation depends on whether you want to allow the user to specify complex paths with multiple components that may span multiple folders, or only simple filenames without a path component.
-
+In the former case, a common strategy is to make sure that the constructed file path is contained within a safe root folder.
+First, normalize the path using path.resolve or fs.realpathSync to remove any ".." segments.
+Then check that the normalized path starts with the root folder.
+Note that the normalization step is important, since otherwise even a path that starts with the root folder could be used to access files outside the root folder.
+
+In the latter case, you can use a library like the sanitize-filename npm package to eliminate any special characters from the file path.
+Note that it is not sufficient to only remove "../" sequences: for example, applying this filter to ".../...//" would still result in the string "../".
+
+Finally, the simplest (but most restrictive) option is to use an allow list of safe patterns and make sure that the user input matches one of these patterns. +
-In the first example, a file name is read from an HTTP request and then used to access a file.
-However, a malicious user could enter a file name which is an absolute path, such as
-"/etc/passwd".
-
-In the second example, it appears that the user is restricted to opening a file within the
-"user" home directory. However, a malicious user could enter a file name containing
-special characters. For example, the string "../../etc/passwd" will result in the code
-reading the file located at "/home/user/../../etc/passwd", which is the system's
-password file. This file would then be sent back to the user, giving them access to all the
-system's passwords.
+In the first example, a file name is read from an HTTP request and then used to access a file within a root folder.
+However, a malicious user could enter a file name containing "../" segments to navigate outside the root folder and access sensitive files.
+The second example shows how to fix this.
+First, the file name is resolved relative to a root folder, which has the side effect of normalizing the path and removing any "../" segments.
+Then, fs.realpathSync is used to resolve any symbolic links in the path.
+Finally, we check that the normalized path starts with the root folder's path, which ensures that the file is contained within the root folder.
+