Description
Inadequate input validation can let an application access or modify files outside a restricted directory, exposing sensitive information or damaging files.
Potential impact
- Sensitive data exposure through access outside the restricted directory
- Unauthorized file writes or overwrites
Remediation
- Normalize and validate input before passing it to path-combining functions.
- If only a filename is needed, use
path.basename()to extract the final component and combine it with a trusted base directory. - Filter disallowed characters or directory paths, and verify that the normalized result remains inside the base directory.
- Restrict the process's file access permissions to what it needs.
Examples
Before
javascript
const path = require("path");
function unsafePathTraversal(user_input) {
return path.join("/safeDir", user_input);
}
After
javascript
const path = require("path");
function safePathTraversal(user_input) {
const baseDir = path.resolve("/safeDir");
// For filename-only input, remove directory components and allow only permitted characters.
const filename = path.basename(String(user_input || ""));
if (!/^[a-zA-Z0-9._-]+$/.test(filename)) {
return 'Access Denied';
}
const pathString = path.resolve(baseDir, filename);
if (!pathString.startsWith(baseDir + path.sep)) {
return 'Access Denied';
}
return pathString;
}
Explanation:
- Before: Unvalidated input is combined with a path, allowing attacker-controlled values to escape the restricted directory.
- After: For filename-only input,
path.basename()removes directory components. Character validation and a base-directory check keep the resulting path string within that directory. Subdirectory paths also need a containment check after normalization. This example does not resolve filesystem links; actual file access must account for symbolic links and paths changing after validation.