GitHub Advisoryadvisory · Go
GHSA-8mcq-6wmr-jrjv Excelize: a row whose earlier cell has a higher column reference than its last cell panics index out of range on almost every worksheet read API
MEDIUM
Official page ↗
- Aliases
- CVE-2026-107221
- Ecosystem
- Go
- Packages
- github.com/xuri/excelize/v2
- Severity
- Moderate
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H
- Weaknesses
- CWE-787
- Reviewed
- 2026-10-07
Affected packages
• Go github.com/xuri/excelize/v2: >= 2.0.0, < 2.11.1-0.20260816084418-46a5eb289448 → fixed in 2.11.1-0.20260816084418-46a5eb289448
Description
Affected versions and vulnerable location
• Confirmed at `ae2113b` (current HEAD).
• Sink: `rows.go:967` `ws.SheetData.Row[rowIdx].C[colNum-1] = *colData` inside `checkRow`.
• `checkRow` computes `lastCol` from the column of the last cell in document order (`rows.go:940`), allocates `targetList` of that length, then re-scatters every source cell into `C[colNum-1]`.
Root cause
The slice is sized from the last cell's column, but cells are not required to be column-sorted in the XML. A cell that appears earlier in the row but references a higher column than the last cell has `colNum-1 >= len(targetList)`, so the assignment writes out of range. `MaxColumns`/`TotalRows` do not help, every individual column is valid; the bug is the ordering assumption, not magnitude.
Attacker model and reachability
Any service that opens an untrusted spreadsheet and calls a worksheet API that goes through `workSheetReader -> checkRow` (`excelize.go:332`): `GetCellValue`, `GetCellFormula`, `CalcCellValue`, `GetMergeCells`, `SetCellValue`, and essentially every non-streaming worksheet call. (The streaming `GetRows`/`Rows()` SAX path does not trigger it.) Unauthenticated, deterministic, unrecovered panic -> process crash.
Proof of concept (executed)
Crafted `xl/worksheets/sheet1.xml` with a row whose cells are out of column order and whose earlier cell exceeds the last cell's column:
```xml
43
```
`GetCellValue("Sheet1","A1")` (via `getCellStringFunc -> workSheetReader -> checkRow`) panicked `index out of range [3] with length 3` at `rows.go:967`.
Confirming grep:
```bash
rg -n "func checkRow|lastCol|Row\[rowIdx\].C\[colNum-1\]" rows.go
```
Suggested fix
Size `targetList` from the maximum cell column in the row (not the last cell in document order), or bounds-check `colNum-1` against `len(targetList)` and grow the slice as needed before the assignment.
Related
Alias · CVE (1)
- CVE-2026-107221 Excelize is a Go language library for reading and writing Microsoft Excel spreadsheets. vulnerability
Weakness · CWE (1)
- CWE-787 Out-of-bounds Write weakness