{"id":"CVE-2026-128339","kind":"vulnerability","aliases":["CVE-2026-128339"],"related":[],"title":"ExcelJS: crafted workbook exhausts memory and crashes applications parsing it","description":"ExcelJS through 4.4.0 contains a memory exhaustion vulnerability in Worksheet._parseMergeCells that allows attackers to crash applications by supplying unbounded mergeCell ranges. Attackers can craft a small workbook with a mergeCell ref like A1:XFD1048576, causing xlsx.load() to create billions of Row and Cell objects and abort the process.","summary":"ExcelJS through 4.4.0 fails to bound merged-cell ranges when parsing a spreadsheet, so a small crafted workbook with a huge merge range makes xlsx.load() create billions of objects. An attacker who can supply a spreadsheet to the application can crash the process.","severity":"high","cvss":8.7,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"exceljs","fixed":[],"affected":"<= 4.4.0","ecosystem":"npm"},{"name":"exceljs-hardened","fixed":["5.1.0"],"affected":"<= 5.0.2","ecosystem":"npm"}],"ecosystems":[],"tags":["exceljs","file-upload","node","nodejs","package"],"not_affected_if":["trusted-input-only","writes-only-workbooks"],"how_to_check":"- Run npm ls exceljs (and npm ls exceljs-hardened) in each project that parses uploaded or external .xlsx files. exceljs <= 4.4.0 is affected; exceljs-hardened <= 5.0.2 is affected.\n- Search for xlsx.load( / xlsx.readFile( calls on untrusted input. The abort is a fatal V8 out-of-memory error, so try/catch does not stop it and the whole process dies.","fix":"No released fix for upstream exceljs (latest 4.4.0 is affected). Fix PR exceljs/exceljs#3114 is open and unmerged. The fork exceljs-hardened is fixed in 5.1.0 (affected <= 5.0.2). Until a release: reject untrusted .xlsx input, or check the zip's xl/worksheets/*.xml for mergeCell refs spanning more than a few thousand cells before calling xlsx.load().","status":"open","published_at":"2026-11-13T10:18:14+00:00","first_seen_at":"2026-11-13T10:47:34+00:00","triaged_at":"2026-11-13T10:49:20+00:00","updated_at":"2026-11-13T10:51:14+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-11-13T10:49:20Z","model":"claude-haiku-5-5","output":{"fix":"- unknown","reach":"internet","title":"ExcelJS: crafted workbook exhausts memory and crashes applications parsing it","impact":"low","summary":"ExcelJS through 4.4.0 fails to bound merged-cell ranges when parsing a spreadsheet, so a small crafted workbook with a huge merge range makes xlsx.load() create billions of objects. An attacker who can supply a spreadsheet to the application can crash the process.","audience":"developers","category":"package","nicknames":[],"who_cares":["exceljs","node","nodejs","file-upload"],"confidence":0.6,"fix_status":"unknown","needs_auth":"no","worst_case":"Attacker crashes the process with a small malicious spreadsheet","analyst_note":"Confirm the fixed version from the GitHub advisory and the VulnCheck page; the sources given do not state a patched release.","how_to_check":"- Check the installed version with `npm ls exceljs` in each project that parses uploaded or external .xlsx files.\n- Search for calls to `xlsx.load(` or `workbook.xlsx.load(` that handle untrusted input.","plain_action":"","product_name":"","needs_analyst":true,"not_affected_if":["writes-only-workbooks","trusted-input-only"],"who_is_affected":"Applications that use ExcelJS to read spreadsheets supplied by users or other outside sources are exposed, because a crafted mergeCell range can exhaust memory during load. Applications that only write workbooks or only read files they control can skip it.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"no","severity_if_unknown":"high"},"cost_usd":0.000742,"input_tokens":4635,"output_tokens":557,"severity_before":"high"},"analyst_status":"done","analyst_note":"Confirm the fixed version from the GitHub advisory and the VulnCheck page; the sources given do not state a patched release.","search":"'-128339':12A,15A '-2026':11A,14A '4.4.0':29B,73C 'a1':103C 'abort':116C 'allow':82C 'applic':8A,66B,86C 'attack':58B,83C,92C 'billion':54B,109C 'bound':32B 'caus':105C 'cell':35B,113C 'contain':74C 'craft':2A,44B,94C 'crash':7A,68B,85C 'creat':53B,108C 'cve':10A,13A 'excelj':1A,20B,27B,71C 'exceljs':16A,18A 'exceljs-hardened':17A 'exhaust':4A,77C 'fail':30B 'file':22B 'file-upload':21B 'hardened':19A 'huge':48B 'like':102C 'make':51B 'memori':5A,76C 'merg':34B,49B 'mergecel':90C,100C 'merged-cel':33B 'node':24B 'nodej':25B 'object':56B,114C 'packag':26B 'pars':9A,38B 'process':70B,118C 'rang':36B,50B,91C 'ref':101C 'row':111C 'small':43B,96C 'spreadsheet':40B,63B 'suppli':61B,88C 'unbound':89C 'upload':23B 'vulner':78C 'workbook':3A,45B,97C 'worksheet._parsemergecells':80C 'xfd1048576':104C 'xlsx.load':52B,106C","nicknames":[],"mitigations":[],"who_affected":"Node.js services that use ExcelJS (exceljs up to 4.4.0, or the exceljs-hardened fork up to 5.0.2) to read .xlsx files from users or other outside sources. A ~6 KB workbook with a mergeCell ref of A1:XFD1048576 crashes the whole process, including other requests it serves. Apps that only write workbooks or only read files they control can skip it.","tier":"B","verified":{"fix":{"at":"2026-11-13T10:51:14Z","by":"analyst","doc":"https://github.com/mateocallec/exceljs-hardened/security/advisories/GHSA-wh3v-83h4-rwwq","run_id":3858}},"analyst_revisit_at":null,"fix_status":"none","audience":"developers","plain_action":null,"pkeys":["exceljs","exceljshardened"],"ptokens":["exceljs","hardened"],"labels":["exceljs","fileupload","high","node","nodejs","package"],"campaign_type":null,"search_a":"'-128339':12A,15A '-2026':11A,14A 'applic':8A 'craft':2A 'crash':7A 'cve':10A,13A 'excelj':1A 'exceljs':16A,18A 'exceljs-hardened':17A 'exhaust':4A 'hardened':19A 'memori':5A 'pars':9A 'workbook':3A","search_b":"'4.4.0':29B 'applic':66B 'attack':58B 'billion':54B 'bound':32B 'cell':35B 'craft':44B 'crash':68B 'creat':53B 'excelj':20B,27B 'fail':30B 'file':22B 'file-upload':21B 'huge':48B 'make':51B 'merg':34B,49B 'merged-cel':33B 'node':24B 'nodej':25B 'object':56B 'packag':26B 'pars':38B 'process':70B 'rang':36B,50B 'small':43B 'spreadsheet':40B,63B 'suppli':61B 'upload':23B 'workbook':45B 'xlsx.load':52B","search_c":"'4.4.0':73C 'a1':103C 'abort':116C 'allow':82C 'applic':86C 'attack':83C,92C 'billion':109C 'caus':105C 'cell':113C 'contain':74C 'craft':94C 'crash':85C 'creat':108C 'excelj':71C 'exhaust':77C 'like':102C 'memori':76C 'mergecel':90C,100C 'object':114C 'process':118C 'rang':91C 'ref':101C 'row':111C 'small':96C 'suppli':88C 'unbound':89C 'vulner':78C 'workbook':97C 'worksheet._parsemergecells':80C 'xfd1048576':104C 'xlsx.load':106C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-10-16T16:00:57+00:00","kev":null,"cvss_vector":"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/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","cvss_by":"disclosure@vulncheck.com","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-128339","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-128339","severity":null,"published_at":"2026-11-13T10:18:14+00:00","modified_at":"2026-11-13T10:18:14+00:00","first_seen_at":"2026-11-13T10:47:34+00:00","fetched_at":"2026-11-13T10:47:34+00:00","note":null},{"source":"analyst","external_id":"CVE-2026-128339:3858","url":"https://github.com/exceljs/exceljs/issues/3107","severity":null,"published_at":"2026-11-13T10:51:14+00:00","modified_at":"2026-11-13T10:51:14+00:00","first_seen_at":"2026-11-13T10:51:14+00:00","fetched_at":"2026-11-13T10:51:14+00:00","note":"Triage's GHSA link is for the fork exceljs-hardened (fixed 5.1.0), not upstream exceljs. Upstream exceljs: issue #3107 open, fix PR #3114 open/unmerged, no patched release. Not exploited; PoC is in the issue and the advisory.","cites":["https://github.com/exceljs/exceljs/issues/3107","https://github.com/exceljs/exceljs/pull/3114"]}],"documents":[{"id":145479,"url":"https://github.com/mateocallec/exceljs-hardened/security/advisories/GHSA-wh3v-83h4-rwwq","title":"Vendor advisory: github.com","kind":"vendor","source":"nvd","publisher":"vendor","text":null,"published_at":"2026-10-16T16:00:57+00:00","relation":"advisory","confidence":null,"note":"Vendor advisory: github.com"},{"id":145480,"url":"https://www.vulncheck.com/advisories/exceljs-through-4.4.0-memory-exhaustion-via-oversized-merged-cell-range","title":"Third-party advisory: www.vulncheck.com","kind":"advisory","source":"nvd","publisher":"research","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Third-party advisory: www.vulncheck.com"},{"id":145522,"url":"https://github.com/exceljs/exceljs/issues/3107","title":"exceljs #3107: xlsx.load aborts with heap OOM on a large mergeCell range","kind":"issue","source":"analyst","publisher":null,"text":null,"published_at":null,"relation":"describes","confidence":null,"note":null},{"id":145523,"url":"https://github.com/exceljs/exceljs/pull/3114","title":"ExcelJS PR #3114: reject oversized merge ranges (different bug, open)","kind":"issue","source":"analyst","publisher":null,"text":null,"published_at":null,"relation":"fix","confidence":null,"note":null}],"disclosures":[],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}