~ / search / GHSA-c85p-xxjj-2r75

GHSA-c85p-xxjj-2r75

Excelize ColumnNameToNumber: int64 overflow yields an out-of-domain coordinate with nil error, causing negative slice index panic on r="0" rows

Source: GitHub Advisory Database (reviewed) High CVE-2026-107217

Packages

EcosystemPackageAffectedFixed in
Go github.com/xuri/excelize/v2 >= 2.0.0, < 2.11.1-0.20260910071107-696050fbf14e 2.11.1-0.20260910071107-696050fbf14e
Go github.com/xuri/excelize >= 1.1.0, <= 1.4.1 no fix listed

Details

As written in the advisory (Markdown source, shown as plain text).

### Summary `ColumnNameToNumber` (lib.go:220-237) accumulates the bijective base-26 value of a column name in an int64 with only an upper-bound check (`col > MaxColumns`) applied after the loop and no overflow detection. A 14-letter column name whose true value is 3·2⁶⁴ — e.g. **`VGWQHXLSDVIKWV`** — wraps to `col = 0` and passes the guard, so `CellNameToCoordinates("VGWQHXLSDVIKWV1")` returns `(col=0, row=1, err=nil)`. When normalizing a `r="0"` row, `checkSheetR0` (excelize.go:417-443, called from `checkSheet` at excelize.go:405) runs its `checkRow` closure with `col = 0`: `colIdx := col - 1` becomes **-1**, and `sheetData.Row[rowIdx].C[-1]` (excelize.go:424) raises an unrecovered `panic: runtime error: index out of range [-1]`, killing the host process. ### Details - The row side of the same coordinate gate is enforced (`checkRowNum` at excelize.go:342-350 bounds `r` before the `make([]xlsxRow, row)` allocation; this includes the fix for GHSA-h69g-9hx6-f3v4 / CVE-2026-54063, present in the audited commit). The **column** side is not: `checkSheet`/`lastRowNum`/`checkSheetR0` treat `err == nil` from `CellNameToCoordinates` as proof of an in-domain coordinate (excelize.go:356, :438), which is unsound because of the wrap-around above. - The same unsound gate also feeds `ws.SheetData.Row[rowIdx].C[colNum-1]` in `xlsxWorksheet.checkRow` (rows.go:969): a row combining a valid large column (e.g. `XFD1`) with an overflowed column panics identically. - Reachable from any `workSheetReader`-based API on an attacker-supplied worksheet: `GetCellValue`, `GetCellFormula`, `SetCellValue`, `GetMergeCells`, `GetSheetDimension`, `GetColWidth`, `AddTable`, etc. - Probe on pristine master: `ColumnNameToNumber("VGWQHXLSDVIKWV")` returns `(0, nil)`. - This is a distinct root cause from GHSA-h69g-9hx6-f3v4 (row-index allocation): different mechanism (int64 wrap-around → negative index, not oversized allocation), different sink, different fix. ### PoC A standalone program (public API only) was provided to the maintainer by email (`3-column-overflow`): it builds a workbook in memory whose `xl/worksheets/sheet1.xml` contains `<sheetData><row r="0"><c r="VGWQHXLSDVIKWV1" t="inlineStr"><is><t>pwn</t></is></c></row></sheetData>` (<1 KB of attacker XML), calls `OpenReader`, then `GetCellValue("Sheet1", "A1")` → `PANIC_REPRODUCED: runtime error: index out of range [-1]` on master `ecd99d761fe0` (2026-09-08). With the proposed patch the same program prints `NO_PANIC_BLOCKED`. ### Impact A <1 KB crafted `.xlsx` crashes any service that opens a user-supplied spreadsheet and reads it — upload processing, mail-scanning pipelines, spreadsheet conversion endpoints. Remote, unauthenticated, no privileges. ### Proposed fix Bound the accumulated value inside the loop: check `col > MaxColumns` after each digit. Every digit is at least 1, so any name whose true value exceeds MaxColumns crosses the bound inside the loop, before the accumulation can wrap or overflow — this provably covers all cases, including wraps that would land back inside `[1, MaxColumns]`. A complete patch has been provided to the maintainer.

References

External links from the advisory. They lead to third-party sites.