{"id":"CVE-2026-128346","kind":"vulnerability","aliases":["CVE-2026-128346"],"related":[],"title":"ExcelJS: streaming workbook parser leaks temp files and file descriptors","description":"ExcelJS through 4.4.0 contains a resource leak vulnerability in the streaming WorkbookReader.parse that leaves temporary files and open descriptors when sheet parsing fails or iteration stops early. Attackers can repeatedly upload malformed multi-sheet workbooks with worksheets placed before xl/sharedStrings.xml to fill the temporary directory and exhaust file descriptors.","summary":"ExcelJS up to 4.4.0 leaves temporary files and open file descriptors behind when streaming WorkbookReader.parse fails or iteration stops early. Repeated uploads of crafted multi-sheet workbooks can fill the temp directory and exhaust descriptors (DoS). The GitHub advisory is published on the fork exceljs-hardened (fixed in 5.1.0); no fix for upstream exceljs was found.","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","exceljs-hardened","file-upload","node","npm","package","streaming-reader"],"not_affected_if":["no-streaming-reader","no-untrusted-uploads","write-only-usage"],"how_to_check":"Run `npm ls exceljs exceljs-hardened`. Exposed if exceljs <= 4.4.0 (or exceljs-hardened <= 5.0.2) AND code uses `new ExcelJS.stream.xlsx.WorkbookReader(...)` (grep for WorkbookReader) on untrusted uploads in a long-running process. Symptom: many tmp-* files accumulating in os.tmpdir() and EMFILE errors.","fix":"exceljs: no fixed release found; latest is 4.4.0 and the upstream issue exceljs/exceljs#2147 is open. exceljs-hardened (a fork): upgrade to 5.1.0 per its advisory. Interim: avoid the streaming WorkbookReader for untrusted files, cap upload size/rate, and clean stale tmp files / restart workers.","status":"open","published_at":"2026-11-13T10:18:15+00:00","first_seen_at":"2026-11-13T10:47:35+00:00","triaged_at":"2026-11-13T10:49:12+00:00","updated_at":"2026-11-13T10:50:01+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-11-13T10:49:12Z","model":"claude-haiku-5-5","output":{"fix":"unknown","reach":"internet","title":"ExcelJS: streaming workbook parser leaks temp files and file descriptors","impact":"medium","summary":"ExcelJS up to 4.4.0 leaves temporary files and open file descriptors behind when its streaming WorkbookReader.parse fails or stops early. An attacker who repeatedly uploads crafted multi-sheet workbooks can fill the temporary directory and exhaust file descriptors, causing denial of service.","audience":"developers","category":"package","nicknames":[],"who_cares":["exceljs","node","file-upload"],"confidence":0.6,"fix_status":"unknown","needs_auth":"unknown","worst_case":"Repeated requests exhaust temp directory and file descriptors, causing denial of service.","analyst_note":"Confirm the fixed version and the vendor advisory on github.com and vulncheck.com, since the sources given do not state a fix.","how_to_check":"- Check the installed version with `npm ls exceljs` in the project.\n- Look for a use of `WorkbookReader` with `parse()` on untrusted uploads.\n- unknown for a fixed version in the sources given.","plain_action":"","product_name":"","needs_analyst":true,"not_affected_if":["no-untrusted-uploads","no-streaming-reader"],"who_is_affected":"Applications that use ExcelJS's streaming WorkbookReader to parse workbooks uploaded by users or other untrusted sources are exposed. Projects that only write workbooks or parse trusted local files can skip it. The sources do not name a fixed version.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"yes","severity_if_unknown":"high"},"cost_usd":0.00076,"input_tokens":4637,"output_tokens":592,"severity_before":"high"},"analyst_status":"done","analyst_note":"Confirm the fixed version and the vendor advisory on github.com and vulncheck.com, since the sources given do not state a fix.","search":"'-128346':13A,16A '-2026':12A,15A '4.4.0':37B,94C '5.1.0':84B 'advisori':73B 'attack':119C 'behind':45B 'contain':95C 'craft':57B 'cve':11A,14A 'descriptor':10A,44B,69B,110C,141C 'directori':66B,137C 'dos':70B 'earli':53B,118C 'excelj':1A,21B,23B,34B,80B,89B,92C 'exceljs':17A,19A 'exceljs-harden':22B,79B 'exceljs-hardened':18A 'exhaust':68B,139C 'fail':49B,114C 'file':7A,9A,26B,40B,43B,107C,140C 'file-upload':25B 'fill':63B,134C 'fix':82B,86B 'fork':78B 'found':91B 'github':72B 'harden':24B,81B 'hardened':20A 'iter':51B,116C 'leak':5A,98C 'leav':38B,105C 'malform':123C 'multi':59B,125C 'multi-sheet':58B,124C 'node':28B 'npm':29B 'open':42B,109C 'packag':30B 'pars':113C 'parser':4A 'place':130C 'publish':75B 'reader':33B 'repeat':54B,121C 'resourc':97C 'sheet':60B,112C,126C 'stop':52B,117C 'stream':2A,32B,47B,102C 'streaming-read':31B 'temp':6A,65B 'temporari':39B,106C,136C 'upload':27B,55B,122C 'upstream':88B 'vulner':99C 'workbook':3A,61B,127C 'workbookreader.parse':48B,103C 'worksheet':129C 'xl/sharedstrings.xml':132C","nicknames":[],"mitigations":[],"who_affected":"Node apps that parse user-uploaded workbooks with ExcelJS's streaming WorkbookReader in a long-running process (<= 4.4.0), and users of the exceljs-hardened fork <= 5.0.2. Projects that only write workbooks, use the non-streaming reader, or parse trusted files can skip it.","tier":"B","verified":{"products":{"at":"2026-11-13T10:50:01Z","by":"analyst","doc":"https://github.com/mateocallec/exceljs-hardened/security/advisories/GHSA-mp7v-gxhv-42h2","run_id":3853},"how_to_check":{"at":"2026-11-13T10:50:01Z","by":"analyst","doc":"https://github.com/mateocallec/exceljs-hardened/security/advisories/GHSA-mp7v-gxhv-42h2","run_id":3853}},"analyst_revisit_at":null,"fix_status":"none","audience":"developers","plain_action":null,"pkeys":["exceljs","exceljshardened"],"ptokens":["exceljs","hardened"],"labels":["exceljs","exceljshardened","fileupload","high","node","npm","package","streamingreader"],"campaign_type":null,"search_a":"'-128346':13A,16A '-2026':12A,15A 'cve':11A,14A 'descriptor':10A 'excelj':1A 'exceljs':17A,19A 'exceljs-hardened':18A 'file':7A,9A 'hardened':20A 'leak':5A 'parser':4A 'stream':2A 'temp':6A 'workbook':3A","search_b":"'4.4.0':37B '5.1.0':84B 'advisori':73B 'behind':45B 'craft':57B 'descriptor':44B,69B 'directori':66B 'dos':70B 'earli':53B 'excelj':21B,23B,34B,80B,89B 'exceljs-harden':22B,79B 'exhaust':68B 'fail':49B 'file':26B,40B,43B 'file-upload':25B 'fill':63B 'fix':82B,86B 'fork':78B 'found':91B 'github':72B 'harden':24B,81B 'iter':51B 'leav':38B 'multi':59B 'multi-sheet':58B 'node':28B 'npm':29B 'open':42B 'packag':30B 'publish':75B 'reader':33B 'repeat':54B 'sheet':60B 'stop':52B 'stream':32B,47B 'streaming-read':31B 'temp':65B 'temporari':39B 'upload':27B,55B 'upstream':88B 'workbook':61B 'workbookreader.parse':48B","search_c":"'4.4.0':94C 'attack':119C 'contain':95C 'descriptor':110C,141C 'directori':137C 'earli':118C 'excelj':92C 'exhaust':139C 'fail':114C 'file':107C,140C 'fill':134C 'iter':116C 'leak':98C 'leav':105C 'malform':123C 'multi':125C 'multi-sheet':124C 'open':109C 'pars':113C 'place':130C 'repeat':121C 'resourc':97C 'sheet':112C,126C 'stop':117C 'stream':102C 'temporari':106C,136C 'upload':122C 'vulner':99C 'workbook':127C 'workbookreader.parse':103C 'worksheet':129C 'xl/sharedstrings.xml':132C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-10-16T16:06:26+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-128346","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-128346","severity":null,"published_at":"2026-11-13T10:18:15+00:00","modified_at":"2026-11-13T10:18:15+00:00","first_seen_at":"2026-11-13T10:47:35+00:00","fetched_at":"2026-11-13T10:47:35+00:00","note":null},{"source":"analyst","external_id":"CVE-2026-128346:3853","url":"https://github.com/exceljs/exceljs/issues/2147","severity":null,"published_at":"2026-11-13T10:50:01+00:00","modified_at":"2026-11-13T10:50:01+00:00","first_seen_at":"2026-11-13T10:50:01+00:00","fetched_at":"2026-11-13T10:50:01+00:00","note":"GHSA-mp7v-gxhv-42h2 is on the exceljs-hardened fork (affected <=5.0.2, patched 5.1.0), not upstream exceljs; VulnCheck lists exceljs<=4.4.0. Upstream issue #2147 still open, no upstream fix found. Nothing verified: the GHSA is for a different package than the CVE's. Not exploited; PoC is in the GHSA text.","cites":["https://github.com/exceljs/exceljs/issues/2147"]}],"documents":[{"id":145493,"url":"https://github.com/mateocallec/exceljs-hardened/security/advisories/GHSA-mp7v-gxhv-42h2","title":"Vendor advisory: github.com","kind":"vendor","source":"nvd","publisher":"vendor","text":null,"published_at":"2026-10-16T16:06:26+00:00","relation":"advisory","confidence":null,"note":"Vendor advisory: github.com"},{"id":145494,"url":"https://www.vulncheck.com/advisories/exceljs-through-4.4.0-resource-exhaustion-via-streaming-workbookreader-temporary-files","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":145518,"url":"https://github.com/exceljs/exceljs/issues/2147","title":"exceljs #2147: WorkbookReader.parse() doesn't cleanup temporary files if not fully iterated (open)","kind":"issue","source":"analyst","publisher":null,"text":null,"published_at":null,"relation":"mentions","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"}