Path traversal

Path traversal

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.

References