Skip to content

Commit 6c3be2c

Browse files
committed
[NEW] CVE-2026-38358: xlsx unescapexml() Unbounded Recursion DoS
Reserved CVE-2026-38358 (MITRE) for SheetJS xlsx Community Edition (unmaintained since 2022). unescapexml() recursively processes each <![CDATA[...]]> token without depth limit, allowing remote DoS via crafted XLSX file with sequential CDATA tokens in sharedStrings.xml. CVSS: 8.6 HIGH (Scope:Changed) CWE-674: Uncontrolled Recursion No patch (package unmaintained) — users should migrate to xlsx-js-style or exceljs.
1 parent d0f8161 commit 6c3be2c

1 file changed

Lines changed: 69 additions & 0 deletions

File tree

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-PLACEHOLDER-xlsx-cdata-recursion",
4+
"modified": "2026-05-07T00:00:00Z",
5+
"published": "2026-05-07T00:00:00Z",
6+
"aliases": [
7+
"CVE-2026-38358"
8+
],
9+
"summary": "xlsx (SheetJS Community Edition): Unbounded recursion in unescapexml() leads to remote DoS via crafted XLSX files",
10+
"details": "## Summary\n\nSheetJS xlsx Community Edition (all versions including 0.18.5, unmaintained since 2022) contains an unbounded recursion vulnerability in the XML parser's `unescapexml()` function. A crafted XLSX file containing many sequential `<![CDATA[...]]>` tokens in `xl/sharedStrings.xml` causes recursive calls to exhaust the JavaScript call stack, terminating the Node.js process.\n\n**The package is unmaintained.** Users should migrate to `xlsx-js-style` or `exceljs`.\n\n## Vulnerable code (`xlsx.js:3501-3506`)\n\n```javascript\nreturn function unescapexml(text) {\n var s = text + '';\n var i = s.indexOf(\"<![CDATA[\");\n if(i == -1) return s.replace(encregex, ...).replace(coderegex, ...);\n\n var j = s.indexOf(\"]]>\");\n return unescapexml(s.slice(0, i)) + // Recurse on prefix\n s.slice(i+9, j) + // Raw CDATA content\n unescapexml(s.slice(j+3)); // Recurse on suffix — UNBOUNDED\n};\n```\n\n## Recursion mechanics\n\n- Each `<![CDATA[...]]>` token in the string triggers one recursive call on the suffix\n- N sequential tokens = N stack frames\n- JavaScript does not tail-call optimize this pattern\n- No depth counter or iteration limit exists\n\n**Call chain:**\n```\nXLSX.read(buffer)\n → parse_zip()\n → parse_sst_xml() // Shared Strings Table\n → unescapexml(text)\n → unescapexml(suffix) → Recurses N times for N CDATA tokens\n```\n\n## Proof of Concept\n\nAn XLSX file (~126 KB) containing `xl/sharedStrings.xml` with approximately 9,000 sequential `<![CDATA[a]]>` tokens reliably triggers `RangeError: Maximum call stack size exceeded` on Node.js v18+. Crash threshold: ~8,320 tokens (varies by Node.js version).\n\n## Impact\n\nAny application that processes untrusted XLSX files using SheetJS Community Edition is vulnerable. Attack scenarios:\n\n- Web application file upload endpoints accepting `.xlsx`\n- Email gateway scanners auto-processing attachments\n- REST/GraphQL APIs with Excel import functionality\n- Cloud storage with automatic file processing pipelines\n- Batch ETL/data processing pipelines accepting partner-supplied XLSX files\n\nResult: Node.js process termination, denial of service for the affected service.\n\n## Mitigation\n\nNo patch will be released — SheetJS Community Edition is unmaintained.\n\n**Migrate to:**\n- `xlsx-js-style` (community fork of older sheetjs)\n- `exceljs` (actively maintained alternative)\n\nIf migration is not immediately possible:\n- Reject XLSX uploads larger than a strict size threshold (e.g. 1 MB)\n- Pre-scan `xl/sharedStrings.xml` for excessive CDATA token counts before calling `XLSX.read()`\n- Process XLSX parsing in a worker thread or sandboxed subprocess",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:N/A:H"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "npm",
21+
"name": "xlsx"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
}
30+
]
31+
}
32+
],
33+
"database_specific": {
34+
"last_known_affected_version_range": "<= 0.18.5"
35+
}
36+
}
37+
],
38+
"references": [
39+
{
40+
"type": "ADVISORY",
41+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-38358"
42+
},
43+
{
44+
"type": "PACKAGE",
45+
"url": "https://github.com/SheetJS/sheetjs"
46+
},
47+
{
48+
"type": "WEB",
49+
"url": "https://www.npmjs.com/package/xlsx"
50+
},
51+
{
52+
"type": "WEB",
53+
"url": "https://www.npmjs.com/package/xlsx-js-style"
54+
},
55+
{
56+
"type": "WEB",
57+
"url": "https://www.npmjs.com/package/exceljs"
58+
},
59+
{
60+
"type": "WEB",
61+
"url": "https://cwe.mitre.org/data/definitions/674.html"
62+
}
63+
],
64+
"database_specific": {
65+
"cwe_ids": [
66+
"CWE-674"
67+
]
68+
}
69+
}

0 commit comments

Comments
 (0)