Repository navigation
chore(deps): update dependency tmp to v0.2.7 [security] - #3953
Open
renovate[bot] wants to merge 1 commit into
Open
renovate[bot] wants to merge 1 commit into
renovate[bot] wants to merge 1 commit into
Conversation
✅ Deploy Preview for brilliant-pasca-3e80ec canceled.
|
🚀 Performance Test ResultsTest Configuration:
Test Metrics:
📜 Logs |
6 tasks
mkurapov
pushed a commit
that referenced
this pull request
Sep 21, 2026
* chore(deps): bump @babel/core, protobufjs, yaml, webpack, tmp, tar, undici Covers the seven security PRs that still need work: #3954, #3952, #3902, #3826, #3953, #3867, #3849. tmp is scoped to >=0.2.0 so the 0.0.33 copy under inquirer isn't dragged across a major. * chore(deps): bump handlebars, shell-quote, websocket-driver Clears the last three critical advisories. All within-major. * chore(deps): bump babel systemjs transform, devalue, fast-uri, flatted, postcss, svgo, next Single-major highs, one override key each. * chore(deps): range-scoped bumps for brace-expansion, immutable, js-yaml, minimatch, rollup, tar-fs, vite, ws Each major line gets its own bounded key. Several of these packages have a clean newer major in the tree (minimatch 10, tar-fs 3, rollup 4, vite 7.3.6) that an unscoped override would have downgraded. immutable 3.8.3 and vite 4.5.14 have no fix inside their own major, so they stay. Listed in the PR description. * chore(deps): astro 6.4.6, axios 1.18.0 Both are declared deps, so the package.json files move alongside the override rather than drifting from it. astro stays on ~6.4.x. Its remaining advisories only patch in 7.x, which is a major and out of scope here. * chore(deps): sharp 0.35.0, otel jaeger propagator 2.9.0 Both riskier than the rest. sharp ships native binaries so CI linux is the real test, not local darwin. The propagator override is scoped to 2.x. The 1.25.1 copy comes from sdk-trace-node@1.25.1, which backend still pins on the otel v1 line; moving that is an otel migration, not a dep bump. * chore(deps): suppress propagator-jaeger advisory instead of an otel v2 migration GHSA-45rx-2jwx-cxfr affects @opentelemetry/propagator-jaeger 1.25.1, which comes in transitively via the backend's @opentelemetry/sdk-trace-node ^1.25.1. The only real fix is moving the backend's otel SDK deps (resources, sdk-metrics, sdk-trace-node) to the v2 line, which drops propagator-jaeger entirely. I attempted that, plus the exporter realignment it needs (the backend already has @opentelemetry/sdk-node@0.217.0 pulling in v2-era otlp-transformer alongside the v1-era exporter-trace-otlp-grpc/exporter-metrics-otlp-grpc, which crashes trace export outright due to clashing protobufjs globals). Bumping the two grpc exporters to ^0.221.0 to match sdk-node "fixed" that crash but traded it for a different one: v1's Span still has no instrumentationScope field, which the v2-era serializer requires, so export still fails, just with a different stack. Decided not to chase the SDK v2 migration for this pass. Ignoring the GHSA via pnpm.auditConfig.ignoreGhsas instead, so it's a stated, visible suppression rather than a silently reverted fix. `pnpm audit` still lists it, just tagged "(1 ignored)". Separately: telemetry tracing looks broken on this branch (and likely main) any time ENABLE_TELEMETRY_TRACES=true, independent of this GHSA - the sdk-node bump in an earlier merged Renovate PR didn't realign the grpc exporters, so trace export throws on the protobufjs global clash described above. Nothing catches this today since service.test.ts mocks the otel packages wholesale and CI never enables telemetry. Worth a separate look by whoever owns telemetry. * chore(deps): relay-compiler 13 to drop immutable 3 immutable 3.8.3 has two highs and no patched 3.x, so the only way out is to move the thing that depends on it. relay-compiler 13.0.2 wants immutable ^5.1.9, which the existing >=5.0.0 override already covers. relay-operation-optimizer 7.0.0 asks for relay-compiler ^12, but its own latest (7.1.8) asks for ^13.0.2 on the same optimizer major, so the API it uses didn't move. Codegen output is unchanged. Dropped the immutable@>=3.0.0 override since nothing wants immutable 3 now. * chore(deps): vanilla-extract integration 8 to drop vite 4 vite 4.5.14 comes in under @vanilla-extract/integration 6.2.1 via remix's classic compiler in mock-ASE. There's no vite this could upgrade to inside a range 6.x accepts, and vite 5 is out of support so GHSA-fx2h has no 5.x patch. integration v8 has no vite dependency at all, so vite just leaves. v8 renamed createCompiler to compile and remix 2.17.5 still calls createCompiler, but it's only reached from the .css.ts / .vanilla.css onLoad handlers, and the plugin bails out earlier anyway unless the app declares @vanilla-extract/css. mock-ASE does neither. This does become a landmine if mock-ASE ever adopts vanilla-extract. * chore(deps): unscope the tmp override to catch 0.0.33 external-editor is at its latest (3.1.0) and still pins tmp ^0.0.33, so the >=0.2.0 selector never reached that copy. No upstream fix to wait for. external-editor only calls tmp.tmpNameSync, which 0.2.7 still exports with the same signature, and the path is inquirer's editor prompt inside graphql-codegen which never runs interactively here. Forcing it across the 0.x major is the only option that clears GHSA-ph9p-34f9-6g65. * chore(deps): drop npm from the prod runner images Every Grype and Trivy scan was failing on the same 5 highs plus a critical, and none of them were ours. Trivy's paths gave it away: they all sit under /usr/local/lib/node_modules/npm in the base image. node:24-alpine3.23 ships npm 11.17.0, which bundles tar 7.5.16, brace-expansion 5.0.6, ip-address 10.2.0 and undici 6.26.0. I confirmed those versions by hand in the base image and they match the scanner output exactly. That's why the last few override bumps didn't move the needle. Our lockfile already resolves tar 7.5.22 / brace-expansion 5.0.9 / undici 6.28.0, but a pnpm override can't touch a copy of npm baked into the runner image. The runner stages only ever exec node (frontend goes through node_modules/.bin/remix-serve), corepack isn't enabled there, and nothing in localenv or helm shells out to npm inside these containers, so npm is just dead weight. Removing it takes out the whole class of finding rather than this month's batch of it. Built backend and frontend locally and scanned both tarballs: Trivy and Grype both exit 0 at the high cutoff now, and npm no longer shows up anywhere in the scanned path list. Grype passed even without .grype.yaml loaded, so it's clean on its own rather than by suppression. I left the existing ignore rules alone, though some of them may well be stale now. * chore(deps): collapse propagator-jaeger onto v2 The backend image had one high left that was actually ours: @opentelemetry/propagator-jaeger 1.25.1, CVE-2026-59892. The suppression I added earlier only went into pnpm.auditConfig.ignoreGhsas, which covers pnpm audit and nothing else, so Trivy kept failing on it. Turns out this doesn't need the otel v2 migration I backed away from last time. The backend already installs propagator-jaeger 2.10.0 via sdk-node 0.217.0, sitting right next to the 1.25.1 that sdk-trace-node 1.25.1 pulls in. Both were already in the tree. So I widened the override, which was scoped to @>=2.0.0 and therefore matched nothing, to just pin the package, and the two collapse onto 2.10.0. sdk-trace-node 1.x only ever constructs JaegerPropagator and registers it as a TextMapPropagator, so the v1/v2 core split underneath doesn't matter here. Checked it directly: NodeTracerProvider.register() with the v2 propagator works, and an uber-trace-id round-trips through extract/inject with the trace id, span id and flags intact. All 34 telemetry tests pass. Only fixes the one CVE. @opentelemetry/core 1.22.0 and 1.25.1 are still in there under GHSA-8988-4f7v-96qf, but that one's medium and below the scan cutoff, and clearing it does need the SDK v2 move. * chore(deps): record why bumping the base image doesn't help Checked whether a newer tag would let us drop the npm removal. It won't. Every node:24 alpine tag (3.22, 3.23, 3.24 and the floating 24-alpine) is node 24.19.0 with npm 11.17.0 and the same bundled tar 7.5.16 / brace-expansion 5.0.6 / ip-address 10.2.0. Going further up doesn't fix it either. The newest published node image (node:alpine, 26.7.0) ships npm 11.19.0, which is still brace-expansion 5.0.7 and ip-address 10.2.0. Both remain vulnerable to the highs that fail us: GHSA-rgw5 wants 5.0.9, GHSA-mh99 wants 5.0.8, GHSA-mwp4 wants ip-address 10.3.1. So there's no base image at any node version that passes the high cutoff right now, and we're on node 24 per engines anyway. Just trimming the comment down and folding that finding into it, since it's repeated in five files and it's what the next person will want to know. * chore(deps): drop the scanner suppressions that are now dead Three leftovers, none of which match anything anymore. pnpm.auditConfig.ignoreGhsas held GHSA-45rx-2jwx-cxfr for propagator-jaeger 1.25.1. That version is gone from the tree since the override collapsed it onto 2.10.0, so the entry can't match. pnpm audit reports the same 8 low and 23 moderate with it removed, and nothing tagged as ignored. .grype.yaml and .trivyignore both carried CVE-2026-12151 (plus GHSA-vxpw-j846-p89q on the grype side). Scanned all five prod images with no ignore config at all, across every severity, and neither ID shows up. Running grype with the config still loaded reports zero matches ignored, where CI was logging 6 before, so what those rules were catching is fixed now. Removed the files rather than leaving empty ones. Easy enough to re-add, and #3947 set the precedent of pruning these as they get fixed. All five images pass both scanners at CI's exact settings with the files gone. * chore: fail docker if npm rm fail, rm npm doc references * fix: openssl, next, faker, vulns * fix: remove next * fix: posgtres startup error on authed frontend * fix: drop rollup and vite overrides that match nothing --------- Co-authored-by: Blair Currey <12960453+BlairCurrey@users.noreply.github.com>
This branch has not been deployed
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 allows arbitrary temporary file / directory write via symbolic link
dirparameterCVE-2025-54798 / GHSA-52f5-9888-hmc6
More information
Details
Summary
tmp@0.2.3is vulnerable to an Arbitrary temporary file / directory write via symbolic linkdirparameter.Details
According to the documentation there are some conditions that must be held:
Related issue: https://github.com/raszi/node-tmp/issues/207.
The issue occurs because
_resolvePathdoes not properly handle symbolic link when resolving paths:If the
dirparameter points to a symlink that resolves to a folder outside thetmpDir, it's possible to bypass the_assertIsRelativecheck used in_assertAndSanitizeOptions:PoC
The following PoC demonstrates how writing a tmp file on a folder outside the
tmpDiris possible.Tested on a Linux machine.
tmpDirthat points to a directory outside of it$HOME/mydir1(outside thetmpDir):main.jsA Potential fix could be to call
fs.realpathSync(or similar) that resolves also symbolic links.Impact
Arbitrary temporary file / directory write via symlink
Severity
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
tmp has Path Traversal via unsanitized prefix/postfix that enables directory escape
CVE-2026-44705 / GHSA-ph9p-34f9-6g65
More information
Details
Summary
The tmp npm package contains a path traversal vulnerability that allows escaping the intended temporary directory when untrusted data flows into the
prefix,postfix, ordiroptions. By embedding traversal sequences (e.g.,../) or path separators in these parameters, attackers can cause files to be created outside the configured temporary base directory at attacker-controlled locations with the privileges of the running process. This vulnerability affects applications that pass user-controlled data to tmp's file/directory creation functions without proper input sanitization.Details
Root Cause:
The vulnerability exists in tmp's path construction logic where user-supplied options are directly concatenated into file paths without sanitization or validation.
Technical Flow:
<prefix>-<pid>-<random>-<postfix>path.join(tmpDir, opts.dir, name)path.join()normalizes traversal sequences, allowing escapeVulnerable Pattern:
Path Traversal Mechanics:
../../../evilin prefix escapes directory structureopts.diris absolute,path.join()ignorestmpDircompletelypath.join()resolves../sequences regardless of surrounding text..\\), Unix (../), and mixed path systemsKey Vulnerability Points:
prefix,postfix, ordirparameterspath.join()normalization without containment checksPoC
Basic Path Traversal via prefix:
Directory Escape via postfix:
Absolute Path Bypass via dir:
Advanced Multi-Vector Attack:
Real-World Attack Simulation:
Impact
Arbitrary File Creation:
Attack Scenarios:
1. Web Application Configuration Poisoning:
2. Cache Poisoning:
3. Build Pipeline Compromise:
4. Container Escape Attempt:
5. Multi-Tenant Service Bypass:
Business Impact:
Affected Products
Component Impact:
tmp.file()function - vulnerable to prefix/postfix/dir traversaltmp.dir()function - vulnerable to same parameter manipulationtmp.tmpName()function - if using affected path constructionSeverity: High
CVSS v3.1: 8.1 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:L)
CWE Classification:
Remediation
Input Validation and Sanitization:
Secure Implementation Pattern:
Workarounds
For Application Developers:
For Security Teams:
Detection and Monitoring
Static Analysis:
Runtime Detection:
File System Monitoring:
Acknowledgements
Reported by: Mapta / BugBunny_ai
Severity
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:PReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
tmp: 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: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.