Node.js › Path & OS Modules

What is path traversal, and how does the path module (specifically path.normalize() and careful path.join() usage) help prevent it as a security vulnerability?

Advanced

Answer

Path traversal is a vulnerability where user-supplied input containing '../' sequences is used to construct a file path, potentially letting an attacker escape an intended directory and access arbitrary files elsewhere on the filesystem (like reading /etc/passwd via a crafted upload filename) -- prevention involves normalizing and validating that a constructed path still remains within the intended base directory after resolution, since path.join() alone does normalize '..' segments but doesn't prevent them from still resulting in a path outside the intended directory.
const path = require('node:path');

function getSafeFilePath(baseDir, userSuppliedFilename) {
  const resolvedPath = path.resolve(baseDir, userSuppliedFilename);
  if (!resolvedPath.startsWith(path.resolve(baseDir) + path.sep)) {
    throw new Error('Path traversal attempt detected');
  }
  return resolvedPath;
}

// getSafeFilePath('/app/uploads', '../../etc/passwd') -- throws, correctly blocked
Real-world example A file-download endpoint that constructed file paths directly from a user-supplied filename query parameter without validation was found during a security audit to be vulnerable to path traversal, allowing a crafted request to read arbitrary server files outside the intended uploads directory; adding an explicit check that the resolved path stays within the expected base directory closed the vulnerability.

Common follow-ups: Why isn't path.join() alone sufficient to prevent path traversal, even though it does normalize '..' segments within the resulting path?;What additional validation (like filename allowlisting) would provide defense in depth beyond just this path-containment check?