{"id":"CVE-2026-107217","aliases":["EUVD-2026-94547","GHSA-c85p-xxjj-2r75","GO-2026-6677"],"status":"published","title":"Excelize ColumnNameToNumber: int64 overflow yields an out-of-domain coordinate with nil error, causing negative slice index panic on r=\"0\" rows","description":"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.","severity":{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-12","score":0.00363,"percentile":0.30523,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-129","CWE-190"],"published":"2026-10-07T18:26:55Z","modified":"2026-11-05T23:25:41Z","fixes":[{"ecosystem":"Go","package":"github.com/xuri/excelize/v2","fixed_in":["2.11.1-0.20260910071107-696050fbf14e"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"Go","package":"github.com/xuri/excelize/v2","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.0.0"},{"fixed":"2.11.1-0.20260910071107-696050fbf14e"}]}]},{"source":"ghsa","ecosystem":"Go","package":"github.com/xuri/excelize","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"1.1.0"},{"last_affected":"1.4.1"}]}]},{"source":"osv","ecosystem":"Go","package":"github.com/xuri/excelize/v2","ranges":[{"type":"SEMVER","events":[{"introduced":"2.0.0"},{"fixed":"2.11.1-0.20260910071107-696050fbf14e"}]}]},{"source":"osv","ecosystem":"Go","package":"github.com/xuri/excelize","ranges":[{"type":"SEMVER","events":[{"introduced":"1.1.0"},{"last_affected":"1.4.1"}]}]}],"products":[{"vendor":"excelize","product":"excelize"},{"vendor":"qax-os","product":"excelize"}],"references":[{"url":"https://github.com/qax-os/excelize/security/advisories/GHSA-c85p-xxjj-2r75","tags":["x_refsource_CONFIRM","exploit","Exploit","Vendor Advisory","advisory","web"]},{"url":"https://github.com/qax-os/excelize/pull/2394","tags":["x_refsource_MISC","Issue Tracking","Patch","fix","web"]},{"url":"https://github.com/qax-os/excelize/commit/696050fbf14e74e96a58eef2b16aaf72f381a6a8","tags":["x_refsource_MISC","Patch","fix","web"]},{"url":"https://github.com/advisories/GHSA-c85p-xxjj-2r75"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/107xxx/CVE-2026-107217.json","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-107217","tags":["advisory"]},{"url":"https://github.com/qax-os/excelize","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-107217","title":"Excelize ColumnNameToNumber: int64 overflow yields an out-of-domain coordinate with nil error, causing negative slice index panic on r=\"0\" rows","description":"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.","status":"published","published":"2026-10-07T18:26:55.998Z","modified":"2026-10-08T16:10:25.237Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high","assessor":"cna"}],"cwes":["CWE-190","CWE-129"],"updated_at":"2026-11-02T13:45:14.072357Z"}],"euvd":[{"id":"EUVD-2026-94547","description":"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.","status":"published","published":"2026-10-07T18:26:55Z","modified":"2026-10-08T16:10:25Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high"}],"updated_at":"2026-11-02T17:27:28.108203Z"}],"ghsa":[{"id":"GHSA-c85p-xxjj-2r75","title":"Excelize ColumnNameToNumber: int64 overflow yields an out-of-domain coordinate with nil error, causing negative slice index panic on r=\"0\" rows","description":"### Summary\n\n`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 \u003e 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)`.\n\nWhen 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.\n\n### Details\n\n- 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.\n- 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.\n- Reachable from any `workSheetReader`-based API on an attacker-supplied worksheet: `GetCellValue`, `GetCellFormula`, `SetCellValue`, `GetMergeCells`, `GetSheetDimension`, `GetColWidth`, `AddTable`, etc.\n- Probe on pristine master: `ColumnNameToNumber(\"VGWQHXLSDVIKWV\")` returns `(0, nil)`.\n- 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.\n\n### PoC\n\nA 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 `\u003csheetData\u003e\u003crow r=\"0\"\u003e\u003cc r=\"VGWQHXLSDVIKWV1\" t=\"inlineStr\"\u003e\u003cis\u003e\u003ct\u003epwn\u003c/t\u003e\u003c/is\u003e\u003c/c\u003e\u003c/row\u003e\u003c/sheetData\u003e` (\u003c1 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`.\n\n### Impact\n\nA \u003c1 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.\n\n### Proposed fix\n\nBound the accumulated value inside the loop: check `col \u003e 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.","status":"published","published":"2026-10-07T20:23:31Z","modified":"2026-10-07T20:23:32Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high"}],"cwes":["CWE-129","CWE-190"],"updated_at":"2026-11-02T14:41:28.013673Z"}],"nvd":[{"id":"CVE-2026-107217","description":"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.","status":"published","published":"2026-10-07T19:17:33.957Z","modified":"2026-10-13T14:23:36.643Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high","assessor":"secondary"}],"cwes":["CWE-129","CWE-190"],"updated_at":"2026-11-02T14:12:54.809359Z"}],"osv":[{"id":"CVE-2026-107217","title":"Excelize ColumnNameToNumber: int64 overflow yields an out-of-domain coordinate with nil error, causing negative slice index panic on r=\"0\" rows","description":"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.","status":"published","published":"2026-10-07T18:26:55.998Z","modified":"2026-11-05T23:25:41.328813788Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high"}],"cwes":["CWE-129","CWE-190"],"updated_at":"2026-11-06T00:02:13.631839Z"},{"id":"GHSA-c85p-xxjj-2r75","title":"Excelize ColumnNameToNumber: int64 overflow yields an out-of-domain coordinate with nil error, causing negative slice index panic on r=\"0\" rows","description":"### Summary\n\n`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 \u003e 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)`.\n\nWhen 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.\n\n### Details\n\n- 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.\n- 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.\n- Reachable from any `workSheetReader`-based API on an attacker-supplied worksheet: `GetCellValue`, `GetCellFormula`, `SetCellValue`, `GetMergeCells`, `GetSheetDimension`, `GetColWidth`, `AddTable`, etc.\n- Probe on pristine master: `ColumnNameToNumber(\"VGWQHXLSDVIKWV\")` returns `(0, nil)`.\n- 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.\n\n### PoC\n\nA 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 `\u003csheetData\u003e\u003crow r=\"0\"\u003e\u003cc r=\"VGWQHXLSDVIKWV1\" t=\"inlineStr\"\u003e\u003cis\u003e\u003ct\u003epwn\u003c/t\u003e\u003c/is\u003e\u003c/c\u003e\u003c/row\u003e\u003c/sheetData\u003e` (\u003c1 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`.\n\n### Impact\n\nA \u003c1 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.\n\n### Proposed fix\n\nBound the accumulated value inside the loop: check `col \u003e 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.","status":"published","published":"2026-10-07T20:23:31Z","modified":"2026-11-05T23:25:41.328813788Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high"}],"cwes":["CWE-129","CWE-190"],"updated_at":"2026-11-06T00:02:13.631839Z"}]}}
