Skip to content

Commit 007ec00

Browse files
1 parent 51195e4 commit 007ec00

2 files changed

Lines changed: 187 additions & 0 deletions

File tree

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-fx2h-pf6j-xcff",
4+
"modified": "2026-06-15T17:17:45Z",
5+
"published": "2026-06-15T17:17:45Z",
6+
"aliases": [
7+
"CVE-2026-53571"
8+
],
9+
"summary": "vite: `server.fs.deny` bypass on Windows alternate paths",
10+
"details": "### Summary\n\nThe contents of files that are specified by [`server.fs.deny`](https://vite.dev/config/server-options#server-fs-deny) can be returned to the browser on Windows.\n\n### Impact\n\nOnly apps that match the following conditions are affected:\n\n- explicitly exposes the Vite dev server to the network (using `--host` or [`server.host` config option](https://vitejs.dev/config/server-options.html#server-host))\n- the sensitive file exists in the allowed directories specified by [`server.fs.allow`](https://vite.dev/config/server-options#server-fs-allow)\n- either of:\n - the sensitive file exists in an NTFS volume\n - the dev server is running on Windows and the sensitive file exists in a volume that 8.3 short name generation is enabled (it is enabled by default on system volumes)\n\n### Details\n\nVite’s dev server denies direct access to sensitive files through `server.fs.deny`, including entries such as `.env`, `.env.*`, and `*.{crt,pem}`. However, on Windows, the deny logic does not correctly normalize NTFS ADS path forms before access checks are applied.\nBecause of this, requests such as `/.env::$DATA?raw` are treated as allowed paths, while Windows resolves them to the original file's default data stream.\n\nSimilar to that, Windows allows accessing a file using a different name with the 8.3 short name compatibility feature. Vite did not reject accessing files via them.\n\n### PoC\n```bash\n$ npm create vite@latest\n$ cd vite-project/\n$ npm install\n$ npm run dev\n```\nAccess via browser at `http://localhost:5173/.env::$DATA?raw`\n<img width=\"388\" height=\"129\" alt=\"deecc1315123883cfd0f9c26a002845a\" src=\"https://github.com/user-attachments/assets/895c6012-4e2e-4a35-babb-69bbf3ee7170\" />\n\nExample expected result:\n- `/.env::$DATA?raw` returns the contents of `.env`\n- `/tls.pem::$DATA?raw` returns the contents of `tls.pem`",
11+
"severity": [
12+
{
13+
"type": "CVSS_V4",
14+
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "npm",
21+
"name": "vite"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "8.0.0"
29+
},
30+
{
31+
"fixed": "8.0.16"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 8.0.15"
38+
}
39+
},
40+
{
41+
"package": {
42+
"ecosystem": "npm",
43+
"name": "vite"
44+
},
45+
"ranges": [
46+
{
47+
"type": "ECOSYSTEM",
48+
"events": [
49+
{
50+
"introduced": "7.0.0"
51+
},
52+
{
53+
"fixed": "7.3.5"
54+
}
55+
]
56+
}
57+
],
58+
"database_specific": {
59+
"last_known_affected_version_range": "<= 7.3.4"
60+
}
61+
},
62+
{
63+
"package": {
64+
"ecosystem": "npm",
65+
"name": "vite"
66+
},
67+
"ranges": [
68+
{
69+
"type": "ECOSYSTEM",
70+
"events": [
71+
{
72+
"introduced": "0"
73+
},
74+
{
75+
"fixed": "6.4.3"
76+
}
77+
]
78+
}
79+
],
80+
"database_specific": {
81+
"last_known_affected_version_range": "<= 6.4.2"
82+
}
83+
},
84+
{
85+
"package": {
86+
"ecosystem": "npm",
87+
"name": "vite-plus"
88+
},
89+
"ranges": [
90+
{
91+
"type": "ECOSYSTEM",
92+
"events": [
93+
{
94+
"introduced": "0"
95+
},
96+
{
97+
"fixed": "0.1.24"
98+
}
99+
]
100+
}
101+
],
102+
"database_specific": {
103+
"last_known_affected_version_range": "<= 0.1.23"
104+
}
105+
}
106+
],
107+
"references": [
108+
{
109+
"type": "WEB",
110+
"url": "https://github.com/vitejs/vite/security/advisories/GHSA-fx2h-pf6j-xcff"
111+
},
112+
{
113+
"type": "PACKAGE",
114+
"url": "https://github.com/vitejs/vite"
115+
}
116+
],
117+
"database_specific": {
118+
"cwe_ids": [
119+
"CWE-200",
120+
"CWE-22"
121+
],
122+
"severity": "HIGH",
123+
"github_reviewed": true,
124+
"github_reviewed_at": "2026-06-15T17:17:45Z",
125+
"nvd_published_at": null
126+
}
127+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-h67p-54hq-rp68",
4+
"modified": "2026-06-15T17:15:07Z",
5+
"published": "2026-06-15T17:15:07Z",
6+
"aliases": [
7+
"CVE-2026-53550"
8+
],
9+
"summary": "JS-YAML: Quadratic-complexity DoS in merge key handling via repeated aliases",
10+
"details": "### Summary\nA crafted YAML document can trigger algorithmic CPU exhaustion in `js-yaml` merge-key processing (`<<`) by repeating the same alias many times in a merge sequence. \nThis causes quadratic parse-time behavior relative to input size and can block a Node.js worker/event loop for seconds with a relatively small payload (tens of KB), resulting in denial of service.\n\n### Details\nThe issue is in merge handling inside `lib/loader.js`:\n\n- `storeMappingPair(...)` iterates every element of a merge sequence when key tag is `tag:yaml.org,2002:merge`.\n- For each element, it calls `mergeMappings(...)`.\n- `mergeMappings(...)` computes `Object.keys(source)` and performs `_hasOwnProperty.call(destination, key)` checks for each key.\n\nWhen input is of the form:\n\na: &a {k0:0, k1:0, ..., kK:0}\nb: {<<: [*a, *a, *a, ... repeated M times ...]}\nall *a entries refer to the same anchored object. After the first merge, subsequent merges are semantically no-ops, but the parser still reprocesses all keys each time.\nResulting work is O(K * M), while input size is O(K + M), giving quadratic scaling as payload grows.\nRelevant code path:\nlib/loader.js in storeMappingPair(...) merge branch (keyTag === 'tag:yaml.org,2002:merge')\nlib/loader.js mergeMappings(...)\n\n\n### Root cause\nFile: lib/loader.js\nFunction: storeMappingPair(state, _result, overridableKeys, keyTag, keyNode,\n valueNode, startLine, startLineStart, startPos)\nLines: ~359-366\n\n if (keyTag === 'tag:yaml.org,2002:merge') {\n if (Array.isArray(valueNode)) {\n for (index = 0, quantity = valueNode.length; index < quantity; index += 1) {\n mergeMappings(state, _result, valueNode[index], overridableKeys);\n }\n } else {\n mergeMappings(state, _result, valueNode, overridableKeys);\n }\n }\n\nWhen the merge value is a sequence (YAML 1.1 <<: [ *a, *a, ... ]), each element\nis handed to mergeMappings() without deduplication. mergeMappings() then does\n\n sourceKeys = Object.keys(source);\n for (index = 0; index < sourceKeys.length; index += 1) {\n key = sourceKeys[index];\n if (!_hasOwnProperty.call(destination, key)) {\n setProperty(destination, key, source[key]);\n overridableKeys[key] = true;\n }\n }\n\nEvery alias reference in the sequence resolves (by design) to the SAME object\nvia state.anchorMap. After the first merge, every subsequent merge of that same\nreference is a pure no-op semantically, but still performs:\n\n * one Object.keys(source) call (O(K))\n * K _hasOwnProperty.call checks on the destination\n\nTotal: M * K hasOwnProperty checks + M Object.keys allocations, while the final\nobject and all observable side effects are identical to a single merge.\n\nYAML semantics for `<<:` are idempotent and commutative over duplicate sources,\nso collapsing duplicates preserves behavior exactly; this isn't a spec trade-off.\n\n\n### PoC\nEnvironment:\njs-yaml version: 4.1.1\nNode.js: v24.5.0\nPlatform: arm64 macOS (reproduced consistently)\nReproduction script:\nCreate many keys in one anchored map (&a).\nMerge that same alias repeatedly via <<: [*a, *a, ...].\nMeasure parse time and compare with control payload using single merge (<<: *a).\nObserved repeated runs (same machine):\nK=M=1000, input 9,909 bytes: ~33–36 ms\nK=M=2000, input 20,909 bytes: ~121–123 ms\nK=M=4000, input 42,909 bytes: ~524–537 ms\nK=M=6000, input 64,909 bytes: ~1,608–1,829 ms\nK=M=8000, input 86,909 bytes: ~3,395–3,565 ms\nControl (single merge, similar key counts):\nK=2000: ~1–2 ms\nK=4000: ~3 ms\nK=8000: ~5 ms\nAlso verified: repeated-merge output equals single-merge output (same key count and same JSON), confirming excess time is redundant computation.\n\n\n### Impact\nThis is a denial-of-service vulnerability (CPU exhaustion / algorithmic complexity).\nAny service parsing untrusted YAML with js-yaml can be impacted, including API backends, CI tools, config processors, and automation services. An attacker can submit crafted YAML to significantly increase CPU time and reduce availability.\n\n### Suggested fix:\nDedupe the merge source list by reference before invoking mergeMappings. Any of\nthe following are minimal and preserve YAML 1.1 merge semantics:\n\ndedupe in storeMappingPair:\n\n if (keyTag === 'tag:yaml.org,2002:merge') {\n if (Array.isArray(valueNode)) {\n var seen = new Set();\n for (index = 0, quantity = valueNode.length; index < quantity; index += 1) {\n var src = valueNode[index];\n if (seen.has(src)) continue; // idempotent; skip redundant alias\n seen.add(src);\n mergeMappings(state, _result, src, overridableKeys);\n }\n } else {\n mergeMappings(state, _result, valueNode, overridableKeys);\n }\n }",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "npm",
21+
"name": "js-yaml"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "4.2.0"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 4.1.1"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/nodeca/js-yaml/security/advisories/GHSA-h67p-54hq-rp68"
45+
},
46+
{
47+
"type": "PACKAGE",
48+
"url": "https://github.com/nodeca/js-yaml"
49+
}
50+
],
51+
"database_specific": {
52+
"cwe_ids": [
53+
"CWE-407"
54+
],
55+
"severity": "MODERATE",
56+
"github_reviewed": true,
57+
"github_reviewed_at": "2026-06-15T17:15:07Z",
58+
"nvd_published_at": null
59+
}
60+
}

0 commit comments

Comments
 (0)