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

Excelize ColumnNameToNumber int64 overflow on a 14-letter column name wraps to 0, passing the MaxColumns guard and causing a negative slice index panic on r="0" rows.

- Payout: Research
- Severity: high
- Program: Excelize
- Found by: lmonstergg
- Disclosed: 2026-10-07
- CVE: CVE-2026-107217
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-c85p-xxjj-2r75
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-c85p-xxjj-2r75
- Tags: area:oss domain:oss impact:dos kind:research platform:ghsa sev:high tech:go technique:incomplete-fix technique:source-review vuln:dos vuln:memory-corruption

**Target:** Go library parsing attacker-supplied .xlsx worksheet XML
**Root cause:** ColumnNameToNumber accumulates bijective base-26 in int64 with only a post-loop upper-bound check and no overflow detection, so a 14-letter name whose true value is 3·2⁶⁴ wraps to 0 and passes the guard. Downstream code treats err==nil as proof of an in-domain coordinate, so col-1 becomes -1.
**Steps:**
1. Craft xl/worksheets/sheet1.xml with `<sheetData><row r="0"><c r="VGWQHXLSDVIKWV1" t="inlineStr"><is><t>pwn</t></is></c></row></sheetData>`
2. Call `OpenReader` on the crafted workbook
3. Call `GetCellValue("Sheet1", "A1")`
4. Observe `panic: runtime error: index out of range [-1]` at excelize.go:424 via checkSheetR0's checkRow closure
**How found:** Noticed the row side of the coordinate gate was hardened (checkRowNum bounds r before allocation, per GHSA-h69g-9hx6-f3v4) but the column side was not: checkSheet/lastRowNum/checkSheetR0 trust err==nil from CellNameToCoordinates. Reading ColumnNameToNumber showed only a post-loop MaxColumns check, so they hypothesized an int64 wrap could land back in-domain and probed ColumnNameToNumber("VGWQHXLSDVIKWV") → (0, nil).
**Exploitation:** Attacker supplies a <1 KB .xlsx to any service that opens and reads user spreadsheets (upload processing, mail scanning, conversion endpoints). checkSheetR0 normalizes the r="0" row, computes colIdx = col-1 = -1, and indexes sheetData.Row[rowIdx].C[-1], panicking the host process unauthenticated.
**Insight:** When a fix hardens one axis of a coordinate/range check, audit the sibling axis for the same class; and treat err==nil from a parser as insufficient proof of domain validity when the parser accumulates into fixed-width integers — probe long inputs whose true value is a multiple of 2^64 to wrap back inside the guard.

## Proof of concept (copied exactly from the original report)

**Crafted sheet XML with r=0 and overflowed column**

```
<sheetData><row r="0"><c r="VGWQHXLSDVIKWV1" t="inlineStr"><is><t>pwn</t></is></c></row></sheetData>
```

