Automated Threat Modeling

Brief Summary: CVE-2026-49982 Type-Confusion Path Traversal in node-tmp

CVE-2026-49982 is a high-severity type-confusion path traversal in version 0.2.6 of the node-tmp npm package. It allows file or directory creation outside the intended temporary directory. This review covers detection methods and affected versions.

CVE Analysis

10 min read

ZeroPath CVE Analysis
ZeroPath CVE Analysis

2026-06-11

Brief Summary: CVE-2026-49982 Type-Confusion Path Traversal in node-tmp
Experimental AI-Generated Content

This CVE analysis is an experimental publication that is completely AI-generated. The content may contain errors or inaccuracies and is subject to change as more information becomes available. We are continuously refining our process.

If you have feedback, questions, or notice any errors, please reach out to us.

[email protected]

Introduction

A type-confusion flaw in the popular node-tmp npm package lets attackers create files and directories at arbitrary filesystem locations by sending non-string values through HTTP request parameters. The vulnerability (CVSS 8.2) turns a trusted utility library into a path traversal vector for any Node.js application that passes user-controlled data into temporary file creation without explicit type coercion.

The tmp npm package, maintained at raszi/node-tmp, is a widely used library for creating temporary files and directories in Node.js. It has 773 GitHub stars and is a common utility dependency, so a vulnerability in tmp can cascade across a significant number of downstream applications in the npm ecosystem.

Technical Information

Root Cause: Type-Confusion in _assertPath

The vulnerability is in the _assertPath guard function added in [email protected]. The guard was designed to prevent path traversal by checking whether the prefix, postfix, template, or dir option values contain the .. substring. It does this with the includes('..') method, which behaves differently depending on the type of the receiver.

When a string is passed, String.prototype.includes('..') correctly detects the traversal sequence. When a non-string value such as an Array, Buffer, or arbitrary object is supplied, the semantics change:

  • For Arrays, Array.prototype.includes('..') checks whether any element is strictly equal to the string '..'. It does not check whether the joined string representation of the array contains ../. For example, an array like ['../escape'] returns false from includes('..'), because no element equals exactly '..'. When JavaScript implicitly coerces the same array to a string via Array.prototype.join or String(), the result contains ../.

  • For Buffers, the includes method searches for byte sequences rather than substring patterns in the stringified output. That creates a similar mismatch between what the guard checks and the path that gets constructed.

Once the non-string value passes the _assertPath guard, it flows into _generateTmpName, where JavaScript's implicit string coercion turns it into a string that contains ../ after all. path.join(tmpDir, opts.dir, name) then uses this coerced string, and the final resolved path escapes the intended temporary directory. The host Node.js process creates the file or directory at an attacker-controlled location, with its own privileges.

Attack Vectors

The advisory documents two common delivery mechanisms:

  1. JSON request bodies where a field expected to be a string is an array instead, for example {"prefix": ["../escape"]}. Express's express.json() middleware preserves Array types from parsed JSON, so the array reaches the tmp API intact.

  2. Bracket-notation query strings like ?prefix[]=../escape. Libraries like qs (the default query parser in Express 4, Fastify, and Koa) automatically convert bracket notation into arrays, so the attacker does not even need to send JSON.

Six API functions are affected: tmp.file, tmp.fileSync, tmp.dir, tmp.dirSync, tmp.tmpName, and tmp.tmpNameSync. Each accepts prefix, postfix, and template options that flow through the vulnerable code path.

Relationship to CVE-2026-44705

A second path traversal vulnerability was reported in the same tmp package under CVE-2026-44705 (GHSA-ph9p-34f9-6g65). CVE-2026-49982 exploits type confusion, with non-string values slipping past a string-specific guard. CVE-2026-44705 comes from unsanitized string values for the prefix, postfix, or dir options that contain path traversal sequences directly. The two vulnerabilities have the same consequence but reach it through different bypass mechanisms.

AttributeCVE-2026-49982CVE-2026-44705
GHSA IDGHSA-7c78-jf6q-g5cmGHSA-ph9p-34f9-6g65
Bypass MechanismType confusion (non-string values)Unsanitized string values
Guard Bypassed_assertPath string includes('..') checkNo guard present for string values
Affected Parametersprefix, postfix, template (as non-strings)prefix, postfix, dir (as strings)
Fixed Version0.2.7Not yet confirmed
CWECWE-20, CWE-22CWE-22

Together they show that the input validation in version 0.2.6 was incomplete on both the string and non-string input paths. Organizations must address both.

Detection Methods

Detecting exploitation of CVE-2026-49982 is tricky because the attack specifically bypasses the _assertPath string-level guard. A standard path traversal puts ../ in a string. This one relies on type confusion. The attacker sends a non-string value that passes the guard and still resolves to a traversal path once it is stringified. Many conventional path traversal detectors will not catch it.

Software Composition Analysis (SCA)

The most straightforward detection starts at the dependency level. Any project running [email protected] is vulnerable. Security teams should flag this version in their dependency trees with tools like npm audit, Snyk, or Dependabot. Versions before 0.2.6 are also vulnerable to the broader path traversal (CVE-2026-44705), so only >=0.2.7 should be considered safe.

Static Code Analysis and Code Auditing

The related GHSA-ph9p-34f9-6g65 advisory gives grep patterns for finding dangerous call sites:

# Search for dangerous tmp usage grep -r "tmp\.file.*prefix.*req\|tmp\.file.*postfix.*req" . grep -r "tmp\.dir.*opts\|tmp\.file.*opts" .

These patterns find code that passes request-derived data (req) or generic option objects (opts) into tmp.file or tmp.dir calls. For CVE-2026-49982, also look for call sites that pass values into tmp options without explicit String() coercion. Any code path where req.body.prefix, req.query.prefix, or similar parsed fields flow directly into tmp.file({ prefix }) is exploitable. Express's express.json() preserves Array types, and the default qs parser turns bracket-notation query strings into arrays.

Network and API Layer Detection

The GHSA-7c78-jf6q-g5cm advisory documents two attack shapes that defenders should watch for at the network perimeter:

  1. JSON request bodies with non-string types for prefix, postfix, or template fields, for example {"prefix":["../escape"]} where the field is an Array instead of a string.
  2. Bracket-notation query strings like ?prefix[]=../escape, which qs-based parsers automatically convert into arrays.

WAF or API gateway rules can inspect inbound payloads for prefix, postfix, or template fields that contain Arrays or Objects rather than plain strings. The same rules can flag or block bracket-notation query parameters that target these fields.

Runtime Monitoring

The GHSA-ph9p-34f9-6g65 advisory publishes a runtime detection wrapper that monkey-patches tmp.file to flag suspicious usage:

// Log suspicious tmp operations function monitorTmpUsage() { const originalTmpFile = require('tmp').file; require('tmp').file = function(options = {}, callback) { // Check for suspicious patterns const suspicious = [ options.prefix && options.prefix.includes('..'), options.postfix && options.postfix.includes('..'), options.dir && path.isAbsolute(options.dir) ].some(Boolean); if (suspicious) { console.warn('Suspicious tmp usage detected:', options); } return originalTmpFile.call(this, options, callback); }; }

This monitor has a significant gap. It calls .includes('..') on the option values, which is the same check _assertPath performs and the same check CVE-2026-49982 bypasses. When options.prefix is an Array like ['../escape'], Array.prototype.includes('..') checks for element-level equality (not substring matching), so ['../escape'].includes('..') returns false. To detect the type-confusion vector, extend the monitor with a typeof check that flags any non-string value for prefix, postfix, or template as suspicious.

A more reliable approach validates the output path rather than the input options:

// Monitor for files created outside expected temp areas const originalFile = tmp.file; tmp.file = function(options, callback) { return originalFile(options, (err, path, fd, cleanup) => { if (!err && options.tmpdir) { const relative = require('path').relative(options.tmpdir, path); if (relative.startsWith('..')) { console.warn('Path traversal detected:', path); } } return callback(err, path, fd, cleanup); }); };

This output-validation approach holds up better against CVE-2026-49982 because it catches the traversal after stringification, whatever input type caused it.

File System Monitoring

On Linux systems, inotifywait can watch for unexpected file creation:

# Monitor file creation outside expected temp directories inotifywait -m -r --format '%w%f %e' /tmp /var/tmp | while read file event; do if [[ "$event" == *"CREATE"* && "$file" != /tmp/tmp-* ]]; then echo "Unexpected file creation: $file" fi done

Exploiting CVE-2026-49982 creates files outside the intended temporary base directory. A Node.js process known to use tmp that creates files in unexpected locations is therefore a strong indicator.

Log-Based Indicators

Indicators to look for in application logs:

  • Entries showing non-string values arriving for the prefix/postfix/template parameters (e.g., type: array when the application logs the received parameter type).
  • File creation paths that resolve outside the configured temporary base directory.
  • EACCES: permission denied errors on unexpected system paths (e.g., attempts to write under /etc/). These mean the traversal succeeded in path construction and only OS-level file permissions stopped it.

Formal Detection Signatures

No formalized YARA rules, Sigma rules, Snort/Suricata signatures, or Elastic detection rules specifically targeting CVE-2026-49982 have been published in the major open-source signature repositories so far.

Affected Systems and Versions

The type-confusion bypass described in CVE-2026-49982 affects version 0.2.6 of the tmp npm package. Version 0.2.7 contains the fix.

Versions before 0.2.6 lack the _assertPath guard entirely and are vulnerable to the related CVE-2026-44705 (string-based path traversal). Only versions >=0.2.7 should be considered safe against both vulnerabilities.

An application is affected if it:

  • Uses [email protected] as a direct or transitive dependency.
  • Passes untrusted request data (JSON body fields, query string parameters, or other user-controlled input) into any of the six API functions: tmp.file, tmp.fileSync, tmp.dir, tmp.dirSync, tmp.tmpName, or tmp.tmpNameSync.
  • Does not perform explicit type coercion (e.g., String()) on prefix, postfix, or template option values before passing them to tmp.

Applications using Express with express.json() middleware, or any framework with qs-based query parsing, are particularly at risk, because these automatically preserve Array types from parsed input.

Vendor Security History

The tmp package has disclosed at least two path traversal vulnerabilities within a short span:

  • GHSA-7c78-jf6q-g5cm (CVE-2026-49982): Type-confusion bypass of _assertPath, published June 11, 2026.
  • GHSA-ph9p-34f9-6g65 (CVE-2026-44705): Unsanitized string-valued prefix/postfix/dir options, published May 26, 2026.

Two distinct path traversal flaws in the same version (0.2.6) suggest that the input validation layer introduced in that version was incomplete. The _assertPath guard closed one attack vector and left others open. tmp is also a single-maintainer open-source project, which carries inherent risk. One maintainer is a bottleneck for security response, and a limited contributor base may mean less security review than larger projects receive.

The NVD record for CVE-2026-49982 is currently marked as "Awaiting Enrichment," which is standard for recently published CVEs. The CVSS score of 8.2 comes from the GitHub Security Advisory, not from a formal NIST assessment.

References

Detect & fix
what others miss

Works with
  • GitHub
  • GitLab
  • Bitbucket
  • Azure DevOps Services
  • Gerrit
  • CVS
  • Jira
  • Linear
  • Slack
  • Security Compass
Explore integrations
Security magnifying glass visualization