Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
{
"schema_version": "1.4.0",
"id": "xlsx-zip-bomb-cve-2026-38359",
"modified": "2026-05-07T00:00:00Z",
"published": "2026-05-07T00:00:00Z",
"aliases": [
"CVE-2026-38359"
],
"summary": "xlsx (SheetJS Community Edition): Unvalidated decompression size from ZIP local file headers leads to memory exhaustion DoS",
"details": "## Summary\n\nSheetJS xlsx Community Edition (all versions including 0.18.5, unmaintained since 2022) reads the uncompressed-size field directly from ZIP local file headers without validation and passes it to `Buffer.allocUnsafe()`. An attacker can craft an XLSX file with arbitrary declared decompression sizes (e.g., 1 GB per entry in a 10 KB file), causing multi-gigabyte synchronous memory allocations that result in out-of-memory crashes.\n\n**The package is unmaintained.** Users should migrate to `xlsx-js-style` or `exceljs`.\n\n## Vulnerable code\n\n**Step 1 — Read uncompressed size from ZIP local file header (`xlsx.js:2670`):**\n```javascript\n// Offset 18-22: Compressed size (4 bytes)\nvar _csz = buf.read_shift(4);\n// Offset 22-26: Uncompressed size (4 bytes) — ATTACKER CONTROLLED\nvar _usz = buf.read_shift(4); // NO VALIDATION\n```\n\n**Step 2 — Direct allocation without limits (`xlsx.js:2529`):**\n```javascript\nvar outbuf = new_unsafe_buf(usz ? usz : (1<<18));\n// → Buffer.allocUnsafe(usz) — Direct allocation from attacker value\n// No maximum size check\n// No compression ratio validation\n```\n\n**Weak consistency check (`xlsx.js:2700-2701`):**\n```javascript\nif(csz !== _csz) throw new Error(\"CSZ\");\nif(usz !== _usz) throw new Error(\"USZ\");\n```\n\nThis only verifies that the local file header matches the central directory header. Both are attacker-controlled, so the attacker simply sets both to the same malicious value — providing no protection.\n\n## Attack mechanism\n\nThe attacker modifies ZIP local file headers to set the uncompressed-size field (bytes 22-26) to arbitrarily large values. The parser reads this attacker-controlled value and passes it directly to `Buffer.allocUnsafe()`, triggering multi-gigabyte synchronous memory allocations.\n\n**Required payload:** ~10 KB XLSX file with modified ZIP headers declaring 10 GB total uncompressed size.\n**Result:** Out-of-memory process termination.\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\n- Email gateway scanners\n- REST/GraphQL APIs with Excel import\n- Cloud storage with automatic file processing\n- CI/CD pipelines that process Excel files\n\n## Mitigation\n\nNo patch will be released — SheetJS Community Edition is unmaintained.\n\n**Migrate to:**\n- `xlsx-js-style`\n- `exceljs`\n\nIf migration is not immediately possible:\n- Set strict file size limits BEFORE invoking `XLSX.read()`\n- Process parsing in a memory-limited subprocess (e.g. Node.js `--max-old-space-size`)\n- Pre-scan ZIP local file headers and reject files with implausible uncompressed sizes\n- Use a WebAssembly-sandboxed parser",
"severity": [
{
"type": "CVSS_V3",
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:N/A:H"
}
],
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "xlsx"
},
"ranges": [
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "0"
}
]
}
],
"database_specific": {
"last_known_affected_version_range": "<= 0.18.5"
}
}
],
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-38359"
},
{
"type": "PACKAGE",
"url": "https://github.com/SheetJS/sheetjs"
},
{
"type": "WEB",
"url": "https://www.npmjs.com/package/xlsx"
},
{
"type": "WEB",
"url": "https://www.npmjs.com/package/xlsx-js-style"
},
{
"type": "WEB",
"url": "https://www.npmjs.com/package/exceljs"
},
{
"type": "WEB",
"url": "https://cwe.mitre.org/data/definitions/400.html"
},
{
"type": "WEB",
"url": "https://cwe.mitre.org/data/definitions/409.html"
},
{
"type": "WEB",
"url": "https://en.wikipedia.org/wiki/Zip_bomb"
}
],
"database_specific": {
"cwe_ids": [
"CWE-400",
"CWE-409"
]
}
}