~ 3 min read

Secure Coding Practices in Node.js Against Path Traversal Vulnerabilities

share this story on
Path traversal vulnerabilities were discovered in webpack and backstage npm packages. Learn secure coding practices to prevent path traversal attacks in Node.js applications.

Path traversal vulnerabilities can grant attackers unauthorized access to your file system, potentially leading to data exfiltration, code execution, or server compromise.

In this article I want to mention secure coding practices to prevent these vulnerabilities and analyze real-world examples (CVE-2024-29180, CVE-2024-26150) to illustrate the impact and mitigation strategies.

Real-World Examples of Path Traversal Vulnerabilities

1. CVE-2024-29180: webpack-dev-middleware

This vulnerability resides in the webpack-dev-middleware package. Due to insufficient validation of user-supplied URLs, an attacker can exploit path traversal to access arbitrary files on the developer’s machine.

The following versions of webpack-dev-middleware are affected: version < 5.3.4, >= 6.0.0 < 6.1.2, >= 7.0.0 < 7.1.0

The impact is potential exfiltration of sensitive data (source code, configuration files), and server compromise if critical system files are accessed.

Here’s a Proof-of-Concept (POC) demonstrating the vulnerability:

// Vulnerable webpack configuration (writeToDisk: true)
module.exports = {
  devServer: {
    devMiddleware: {
      writeToDisk: true,
    },
  },
};

// Malicious request to access /etc/passwd
curl localhost:8080/public/..%2f..%2f..%2f..%2f../etc/passwd

The vulnerable code snippet from the webpack-dev-middleware package:

// (webpack-dev-middleware source code)
getFilenameFromUrl(url) {
  const publicPath = ...; // Public path configuration
  const filePath = url.replace(publicPath, '');
  return path.join(outputPath, filePath);
}

The fix is to upgrade to webpack-dev-middleware version 5.3.4 or later, which addresses this vulnerability.

2. CVE-2024-26150: @backstage/backend-common

This vulnerability affects the @backstage/backend-common package. Flawed symlink checks in the resolveSafeChildPath function allow path traversal attacks.

The backstage/backend-common affected version range is: < 0.19.10, >= 0.20.0-next.0 < 0.20.2, >= 0.21.0-next.0 < 0.21.1.

The impact on vulnerable backstage package verssions is unauthorized access to files outside the intended directory.

The following is the vulnerable code snippet from the @backstage/backend-common package:

const targetPath = resolvePath(base, path);

if (!isChildPath(resolveRealPath(base), resolveRealPath(targetPath))) {
  throw new NotAllowedError(
    'Relative path is not allowed to refer to a directory outside its parent',
  );
}

Here too, the fix is to upgrade to @backstage/backend-common version 0.19.10 or later, which includes a fix for this vulnerability.

JavaScript Secure Coding Principles

By adhering to secure coding practices and staying updated on vulnerable package versions, you can significantly reduce the risk of path traversal vulnerabilities in your Node.js applications.

Remember, a layered defense approach that combines secure coding, regular dependency updates, and vulnerability scanning is crucial for maintaining a secure development environment.

Consider the following secure coding principles to protect your Node.js applications against path traversal vulnerabilities:

  • Avoid User-Supplied Path Concatenation: Never directly concatenate user-supplied paths to existing paths before passing them to path.join or path.resolve. This allows attackers to inject malicious path manipulations using sequences like ../.

  • Sanitization is Not Enough: path.normalize is not a standalone security solution. It may remove some redundant path elements but doesn’t prevent traversal attacks. Sanitizing specific characters like .. is also ineffective as attackers can use URL encoding techniques to bypass such filters.

  • Decode User Input Before Resolution: Apply URL decoding functions like decodeURI and decodeURIComponent on user-supplied paths before resolving them. This helps mitigate attempts to exploit encoded path traversal characters.