chore(deps): update dependency tmp to v0.2.7 [security] - autoclosed#329
Closed
team-github-bot wants to merge 1 commit into
Closed
chore(deps): update dependency tmp to v0.2.7 [security] - autoclosed#329team-github-bot wants to merge 1 commit into
team-github-bot wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
0.2.6→0.2.7tmp: Type-confusion bypass of _assertPath allows path traversal via non-string prefix/postfix/template
CVE-2026-49982 / GHSA-7c78-jf6q-g5cm
More information
Details
Summary
The
_assertPathguard added totmp@0.2.6rejects only string values that contain the substring... It is bypassed whenprefix,postfix, ortemplateis supplied as a non-string value (Array, Buffer, or any object) whoseincludes('..')returns falsy but whose stringification still contains../. The value flows throughArray.prototype.join/Stringcoercion inside_generateTmpNameandpath.join(tmpDir, opts.dir, name), producing a final path that escapestmpdirand creates a file or directory at an attacker-controlled location with the host process's privileges.This affects any application that forwards untrusted request data (a common pattern is JSON body fields or
qs-parsed bracket-array query strings such as?prefix[]=...) intotmp.file,tmp.fileSync,tmp.dir,tmp.dirSync,tmp.tmpName, ortmp.tmpNameSyncwithout explicit type coercion.Impact
tmp.dir{,Sync}), which can then host a subsequent symlink swap.CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:L - score 8.1 (High). Network-reachable when the consumer passes request data unchanged.
Affected versions
tmp>= 0.2.6 (the_assertPathguard introduced by commit 7ef2728 / merged in efa4a06f). Earlier releases are vulnerable to the plain string form (already published as a separate advisory) plus this bypass.Vulnerable code
lib/tmp.jsat tagv0.2.6, commit 41f7159:Root cause:
_assertPathassumes its argument is a string. For anArrayargument,Array.prototype.includes('..')checks element equality (so['../escape'].includes('..')isfalse); for an arbitrary object,Object.prototype.includesdoes not exist and a duck-typedincludes: () => falsedefeats the check entirely. In both shapes, the subsequent[...].join('')andpath.join(...)coerce the value to its underlying string, which still contains../.How untrusted data reaches
_assertPathTwo production-realistic shapes that yield a non-string
prefix/postfix/template:express.json()(and any other JSON body parser) preserves the parsed value's type. A body of{"prefix":["../escape"]}reaches the handler as an Array.qs-style bracket-array query strings. Express 4's defaultqsparser turns?prefix[]=../escapeinto['../escape']. The same applies to any framework usingqs(Fastify, Koa with bodyparser, Hapi via configured parsers, etc.).The consumer pattern is the natural one - forward
req.body.prefixdirectly intotmp.file({ prefix, tmpdir })with no developer-side coercion. The 0.2.6 release notes describe the guard as preventing prefix/postfix traversal, so consumers reasonably believe the guard covers the typical input flow.Proof of concept (string vs array)
poc.js(run afternpm install tmp@0.2.6):Observed output on
tmp@0.2.6:End-to-end reproduction (against the deployed npm package)
Install:
victim-server.js- realistic Express app that forwards a JSON body field intotmp.file:Run:
node victim-server.js &Drive three requests from another shell:
Captured transcript (verbatim from the test rig):
Server log:
Observations:
../escape-string) is rejected at_assertPath. The 0.2.6 guard works for plain strings.["../escape-array"]) passes the guard and creates a file at/private/tmp/escape-array-..., outside the tenant base/tmp/tenant-base-3XHwPZ. The file content isattacker-controlled-content. Confirmed withls:Tenant base is empty. The escape is complete.
["../../../etc/poc-tmp-bypass"]) reachesfs.openfor/etc/poc-tmp-bypass-.... The open fails only because of POSIX permissions, not because tmp blocked the path. On a process running as root, or against any world-writable target directory, this would succeed.Negative control with patched build
Applying the suggested fix below and re-running ATTACK 2:
The patched build rejects non-string
prefix/postfix/templatewith a clear type error before the path is constructed.Suggested fix
Patch
_assertPathto require a string argument. The checkvalue.includes('..')is sound only over strings; any non-string with a custom or array-elementincludessemantics bypasses it.Defence-in-depth, recommended in addition to the type check: validate the final resolved path against
tmpdirafter_generateTmpName, similar to what_getRelativePathalready does fordirandtemplate. That way any future bypass through a different vector (e.g., a future Nodepathchange, or a different option) does not exittmpdir.Fix PR
https://github.com/raszi/node-tmp-ghsa-7c78-jf6q-g5cm/pull/1
Credit
Reported by tonghuaroot.
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:LReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Release Notes
raszi/node-tmp (tmp)
v0.2.7Compare Source
Configuration
📅 Schedule: (in timezone Australia/Brisbane)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR has been generated by Mend Renovate.