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

Published Oct 7, 2026
·
Updated

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") → PANICREPRODUCED: runtime error: index out of range [-1] on master ecd99d761fe0 (2026-09-08). With the proposed patch the same program prints NOPANICBLOCKED.

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.

Other sources

Excelize is a Go language library for reading and writing Microsoft Excel spreadsheets. From 2.0.0 to 2.11.0 in github.com/xuri/excelize/v2 and from 1.1.0 to 1.4.1 in github.com/xuri/excelize, ColumnNameToNumber accumulates a bijective base-26 value in int64 without detecting overflow, allowing an invalid long column name to wrap to zero with no error. ColumnNameToNumber accepts the overflowing name VGWQHXLSDVIKWV, after which checkSheetR0 and xlsxWorksheet.checkRow use the wrapped column value as an index. When a crafted worksheet uses an overflowing column name in a row normalized by checkSheetR0 or checkRow, the wrapped zero column becomes a negative slice index during worksheet normalization, allowing an attacker to panic and terminate the calling process. No fixed version is available as of this review.

— MITRE

Affected Software

4 affected componentsFixes available
go/github.com/xuri/excelize/v2>=2.0.0<=2.11.0
go/github.com/xuri/excelize>=1.1.0<=1.4.1
go/github.com/xuri/excelize>=1.1.0<=1.4.1
go/github.com/xuri/excelize/v2>=2.0.0<2.11.1-0.20260910071107-696050fbf14e
2.11.1-0.20260910071107-696050fbf14e

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade go/github.com/xuri/excelize/v2 to a version that resolves this vulnerability.

    Fixed in 2.11.1-0.20260910071107-696050fbf14e
  2. Compensating control

    Patch ColumnNameToNumber so the accumulated column value is checked against MaxColumns after each digit inside the loop, before it can overflow or wrap; reject any column name once col > MaxColumns.

Event History

Oct 7, 2026
CVE Published
via MITRE·06:26 PM
Data Sourced
via MITRE·06:26 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·07:17 PM
DescriptionSeverityWeakness
Advisory Published
via GitHub·08:23 PM
Data Sourced
via GitHub·08:23 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

Which deployments are affected?

Applications using github.com/xuri/excelize/v2 from 2.0.0 through 2.11.0, or github.com/xuri/excelize from 1.1.0 through 1.4.1, are affected. The issue is in the library's worksheet normalization handling.

2

What does an attacker need to trigger the failure?

An attacker needs to supply a crafted worksheet containing an overflowing column name in a row processed by checkSheetR0 or checkRow. The known overflowing column name is VGWQHXLSDVIKWV; no authentication or user interaction is required according to the supplied vector.

3

What is the impact of successful exploitation?

The overflow wraps the column number to zero without an error, which becomes a negative slice index during worksheet normalization. This panics and can terminate the calling process, resulting in denial of service.

4

Is a fixed release available?

No fixed version was available as of the review.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203