CVE-2026-54063
Unbounded Row Index Allocation in Worksheet Parser (checkSheet OOM/Panic DoS)
Summary
The checkSheet() function in github.com/xuri/excelize/v2 uses an attacker-controlled <row r="N"> XML attribute value directly as the length argument to make([]xlsxRow, row) without validating it against the Excel row limit (TotalRows = 1,048,576). A specially crafted XLSX file can trigger two denial-of-service variants: (A) an out-of-memory process kill when r=2147483647 forces a ~16 GB allocation attempt, and (B) a runtime panic via out-of-bounds slice indexing when r=-1. Any service that opens attacker-supplied XLSX files and calls GetCellValue is affected. No authentication is required.
Details
The vulnerable code path is triggered by calling GetCellValue (or any API that internally invokes workSheetReader) on an XLSX file containing a crafted worksheet row element.
Data flow (source → sink):
1. excelize.go:186-193 — OpenReader reads attacker-controlled spreadsheet bytes.
2. excelize.go:216-223 — ZIP reader is created and passed to ReadZipReader.
3. lib.go:43-77 — ZIP entries are read into fileList; worksheet XML is stored by part name.
4. excelize.go:228-229 — XML bytes are stored in f.Pkg.
5. cell.go:71-79 — Public GetCellValue enters the worksheet value-read path.
6. cell.go:1492-1494 — getCellStringFunc calls workSheetReader.
7. excelize.go:313-324 — Worksheet XML is decoded into xlsxWorksheet.
8. xmlWorksheet.go:302-312 — <row r="..."> is deserialized into xlsxRow.R int with no validation (source).
9. excelize.go:357-377 — checkSheet() accumulates the maximum r value; sink: make([]xlsxRow, row) allocates a slice of that size before any bounds check.
Vulnerable code (excelize.go:373-377):
if r.R != 0 && r.R > row {
row = r.R
}
sheetData := xlsxSheetData{Row: make([]xlsxRow, row)} // unbounded allocation
The constant TotalRows = 1048576 is defined in templates.go:190 but is never applied before the make() call in checkSheet(), leaving the allocation fully attacker-cont
⚡ Watch CVE-2026-54063
Get an email if CVE-2026-54063 is added to CISA KEV, gains public exploit code, or a new advisory cites it — max one per day, one-click unsubscribe.
Advisory coverage (2)
External references
Embed the live status
— this badge updates automatically when the KEV or exploit status changes. How to embed it →
[](https://www.csirts.com/cve/CVE-2026-54063)