Back to Blog
high SEVERITY7 min read

How Path Traversal happens in Node.js tmp package and how to fix it

The tmp package version 0.0.33 contained a high-severity path traversal vulnerability (CVE-2026-44705) that allowed attackers to escape temporary directories through unsanitized prefix and postfix parameters. This reddit-app project was upgraded from tmp 0.0.33 to 0.2.7, which implements proper input sanitization to prevent directory traversal attacks and removes the deprecated os-tmpdir dependency.

O
By Orbis AppSec
•Technically reviewed by Anupam Mediratta•Published August 29, 2026•Reviewed August 29, 2026

Answer Summary

CVE-2026-44705 is a path traversal vulnerability (CWE-22) in the Node.js tmp package versions prior to 0.2.6. The vulnerability occurs when unsanitized prefix or postfix parameters contain directory traversal sequences like "../", allowing attackers to escape the temporary directory and write files to arbitrary locations. The fix is to upgrade tmp to version 0.2.7 or later, which sanitizes these parameters and prevents directory escape attacks.

Vulnerability at a Glance

cweCWE-22
fixUpgrade tmp package from 0.0.33 to 0.2.7 with proper input validation
riskArbitrary file write outside intended temporary directory
languageJavaScript (Node.js)
root causetmp 0.0.33 failed to sanitize prefix/postfix parameters containing "../" sequences
vulnerabilityPath Traversal via unsanitized prefix/postfix parameters

Introduction

In a reddit-app Node.js project, Trivy scanner flagged a high-severity path traversal vulnerability in the reddit-app/package-lock.json file. The culprit? The tmp package version 0.0.33, which contained CVE-2026-44705—a vulnerability that allows attackers to escape temporary directory boundaries through unsanitized prefix and postfix parameters. When an application using tmp accepts user-controlled input for temporary file naming, attackers could inject directory traversal sequences like ../../etc/ to write files anywhere on the filesystem, potentially compromising the entire system.

The vulnerability resided in how tmp 0.0.33 handled the optional prefix and postfix parameters when creating temporary files and directories. Without proper sanitization, these parameters could contain path traversal sequences that would be directly concatenated into the final filesystem path, bypassing the intended temporary directory isolation.

The Vulnerability Explained

The tmp package is widely used in Node.js applications to create temporary files and directories. In version 0.0.33, the package accepted prefix and postfix options that would be incorporated into the temporary file path. However, these parameters were not sanitized for directory traversal sequences.

Here's what the vulnerable dependency tree looked like in package-lock.json:

"node_modules/tmp": {
  "version": "0.0.33",
  "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
  "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
  "license": "MIT",
  "dependencies": {
    "os-tmpdir": "~1.0.2"
  },
  "engines": {
    "node": ">=0.6.0"
  }
}

The vulnerability manifests when application code uses tmp with user-influenced input. Consider this attack scenario:

const tmp = require('tmp'); // version 0.0.33

// Attacker controls the prefix through an HTTP parameter
const userPrefix = req.query.prefix; // Contains: "../../etc/cron.d/"

tmp.file({ prefix: userPrefix, postfix: '.sh' }, (err, path, fd) => {
  // Intended: /tmp/tmp-XYZ.sh
  // Actual: /etc/cron.d/tmp-XYZ.sh
  fs.writeFileSync(path, maliciousScript);
});

In this example, an attacker could:
1. Supply ../../etc/cron.d/ as the prefix parameter
2. The tmp library would create a file at /etc/cron.d/tmp-randomID.sh instead of in /tmp/
3. Write a malicious cron job that executes with elevated privileges
4. Achieve arbitrary code execution on the server

The real-world impact for the reddit-app application is severe. If any route handler or background job uses tmp with data derived from Reddit API responses, user comments, or configuration files, an attacker could:
- Overwrite application configuration files to change behavior
- Write to the web server's document root to serve malicious content
- Create files in system directories to escalate privileges
- Delete or corrupt critical application data

The Fix

The security team upgraded tmp from version 0.0.33 to 0.2.7, which includes comprehensive input sanitization. Here's what changed in package-lock.json:

Before (vulnerable):

"node_modules/tmp": {
  "version": "0.0.33",
  "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
  "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
  "license": "MIT",
  "dependencies": {
    "os-tmpdir": "~1.0.2"
  },
  "engines": {
    "node": ">=0.6.0"
  }
}

After (secure):

"node_modules/tmp": {
  "version": "0.2.7",
  "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz",
  "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==",
  "license": "MIT",
  "engines": {
    "node": ">=14.14"
  }
}

Notice several critical improvements:

  1. Version upgrade: From 0.0.33 to 0.2.7, which includes the CVE-2026-44705 fix
  2. Dependency removal: The deprecated os-tmpdir dependency is completely removed, as tmp 0.2.x uses Node.js's built-in os.tmpdir() method
  3. Modern Node.js requirement: The minimum Node.js version increased from 0.6.0 to 14.14, ensuring access to modern security features

The fix was enforced through an npm override in package.json:

"overrides": {
  "tmp": "0.2.7"
}

This override ensures that even if other dependencies in the project require older versions of tmp, npm will force the use of the secure 0.2.7 version throughout the entire dependency tree.

How this specific change solves the problem:

The tmp 0.2.7 version implements strict validation of prefix and postfix parameters:
- Path traversal sequences (../, ..\\) are detected and rejected
- Absolute paths are not permitted in prefix/postfix
- Only safe filename characters are allowed
- The temporary directory boundary is enforced at the library level

This means that even if application code passes unsanitized user input to tmp, the library itself will prevent directory escape attempts. The attack scenario shown earlier would now fail safely:

const tmp = require('tmp'); // version 0.2.7

const userPrefix = req.query.prefix; // Contains: "../../etc/cron.d/"

tmp.file({ prefix: userPrefix, postfix: '.sh' }, (err, path, fd) => {
  // tmp 0.2.7 sanitizes the prefix, stripping traversal sequences
  // Result: /tmp/.._.._etc_cron.d_tmp-XYZ.sh (safe)
  // Or throws an error, depending on configuration
});

Key Takeaways

  • tmp 0.0.33's unsanitized prefix/postfix parameters allowed directory traversal through ../ sequences, enabling arbitrary file writes outside temporary directories
  • The os-tmpdir dependency was completely removed in tmp 0.2.x, reducing the attack surface and eliminating a deprecated dependency
  • npm overrides in package.json ensure consistent security across the entire dependency tree, even when transitive dependencies require older versions
  • Trivy scanner successfully detected CVE-2026-44705 in package-lock.json before the vulnerability could be exploited in production
  • Upgrading from Node.js 0.6.0 to 14.14 minimum requirement ensures access to modern security features and better filesystem isolation primitives

How Orbis AppSec Detected This

  • Source: The vulnerability exists in the tmp package's handling of prefix and postfix parameters, which can be influenced by user input through HTTP requests, API responses, or configuration files
  • Sink: The unsafe path construction in tmp 0.0.33's file() and dir() methods at the point where prefix/postfix are concatenated into filesystem paths without sanitization
  • Missing control: Input validation and path traversal sequence filtering for the prefix and postfix parameters before filesystem path construction
  • CWE: CWE-22 (Improper Limitation of a Pathname to a Restricted Directory)
  • Fix: Upgraded tmp from 0.0.33 to 0.2.7, which implements comprehensive input sanitization and removes the deprecated os-tmpdir dependency

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

CVE-2026-44705 demonstrates how even widely-used utility libraries can contain critical security flaws that persist across years and thousands of dependent projects. The path traversal vulnerability in tmp 0.0.33 could have allowed attackers to write files anywhere on the filesystem, leading to complete system compromise. By upgrading to tmp 0.2.7 and using npm overrides to enforce this version across the dependency tree, the reddit-app project eliminated this attack vector.

The key lesson: dependency security requires continuous monitoring and rapid response. Automated tools like Trivy can detect these vulnerabilities, but the real security improvement comes from acting on those findings—upgrading vulnerable packages, testing the changes, and deploying fixes quickly. Make dependency auditing a regular part of your development workflow, not a once-a-year security review.

Prevention and further reading

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #24

Related Articles

high

clean_path() Path Traversal: rel_path Escapes USERDATA Dir

A path traversal flaw in the `clean_path()` helper let a user-controlled `rel_path` value escape the intended USERDATA directory and reach arbitrary files on disk. The function joined path segments without checking the final result, so `../` sequences in route parameters or query strings could be used to read or write files outside the sandboxed storage area. The fix normalizes the path and verifies it still resolves inside the USERDATA root before returning it, raising an error otherwise.

critical

path.resolve() Path Traversal in Node CLI's Dynamic import()

A Node.js CLI script for validating expression definitions took a file path from `process.argv[2]`, resolved it with `path.resolve()`, and passed the result straight into a dynamic `import()` — with no check that the resolved path stayed inside the working directory. An attacker (or a malicious skill/plugin invocation) could supply traversal sequences to load and execute arbitrary `.js` files from anywhere on disk. The fix adds a boundary check with `path.relative()` and an extension allowlist b

high

bookDir() Path Traversal via Unsanitized bookId Parameter

The `bookDir()` function accepted unsanitized `bookId` values derived from user-created book titles, enabling path traversal attacks through `../` sequences. A fix was applied that validates the identifier using `path.basename()` and throws on mismatch, ensuring all resolved paths remain within `LIBRARY_DIR`.

high

Express `app.get('*')` Wildcard Handler Path Traversal in watch.js

A first-party Express server's wildcard route handler used `req.url.indexOf('font.woff2')` to gate access to a font file, allowing attackers to bypass the substring check with crafted paths. The fix replaces the catch-all handler with explicit route registration.

high

updateCardBg() Follows Unvalidated 302 Location Headers

A background-image updater fetched a configured image URL with manual redirect handling and then re-issued the request to whatever `Location` header came back, with no scheme or host checks. A redirect to `http://169.254.169.254/` or `http://127.0.0.1:<port>/` would have been followed with the original fetch options attached, and the response body written to disk as an image asset. The fix resolves the redirect target against `imgDownloadUrl` and rejects anything that is not HTTPS on the same ho

high

markitdown_bridge.py Path Traversal: Arbitrary File Read via sys.argv

The markitdown_bridge.py script, used by MDView for DOCX-to-Markdown conversion, accepted file paths directly from command-line arguments without validating they stayed within intended directories. An attacker could exploit this to read arbitrary files from the filesystem by passing path traversal sequences in the source_path parameter.