GitHub Advisoryadvisory · Go
GHSA-fq3v-74gv-27gm Excelize: Unbounded <col max> attribute is loaded with no MaxColumns check and expanded per-column by flatCols(), so any column mutator hangs or OOMs the process
HIGH
Official page ↗
- Aliases
- CVE-2026-107223
- Ecosystem
- Go
- Packages
- github.com/xuri/excelize/v2
- Severity
- High
- CVSS vector
- CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
- Weaknesses
- CWE-789
- Reviewed
- 2026-10-07
Affected packages
• Go github.com/xuri/excelize/v2: >= 2.1.0, < 2.11.1-0.20260807015645-a54c578af309 → fixed in 2.11.1-0.20260807015645-a54c578af309
Description
Summary
The `max` attribute of a `` element in `xl/worksheets/sheetN.xml` is read verbatim on open with no check against `MaxColumns`, and `flatCols()` then walks `Min..Max` doing a `deepcopy.Copy` and `append` per iteration. Executed: `max="300000"`, only about 18x past the real 16384 limit, cost 46.2 s of CPU and 122 MB on a single `SetColWidth` call, and the growth is linear in `max` up to 2^31-1.
Confirmed at `ae2113b` (HEAD at the time of audit).
Details
`col.go:547`, `flatCols()`, with the two loops at `:549` and `:564`:
```go
for i := col.Min; i ` block before ``, opened it with `OpenReader`, then called `SetColWidth`.
```xml
```
```go
f.SetColWidth("Sheet1", "A", "A", 12)
```
Measured:
• `max="300000"`: 46.2 s CPU, 122 MB allocated, `ws.Cols.Col` grew to 300000 entries, from one call.
• `max="5000000"`: did not complete in 110 s, killed by the test timeout.
Growth is linear in `max`. At `max=2147483647` that is roughly two billion `xlsxCol` allocations, which is hundreds of gigabytes and in practice a permanent hang ending in OOM.
Impact
Any service that opens an untrusted spreadsheet and calls a column mutator. The input is a few dozen bytes of XML inside an otherwise ordinary workbook, no authentication is involved beyond whatever gates the upload, and the process is either wedged for minutes or killed by the OOM reaper. Availability only; no read or write primitive here.
Suggested fix
Validate `col.Min` and `col.Max` against `MinColumns`/`MaxColumns` when parsing the `` element, or at the top of `flatCols`, returning `ErrColumnNumber` for out-of-range values. That mirrors what `checkRowNum` already does on the row axis.
Why this is not GHSA-h69g-9hx6-f3v4 or GHSA-q5j5-6p94-4gwc
Both of those are row-axis allocation bounds, and both fixes cap at `TotalRows`. Neither touched `` parsing or `flatCols`. This is the same weakness class on the column axis, and it is arguably worse than the two that were fixed, because those had a cap that was bypassed while this one has no cap at all.
Related
Alias · CVE (1)
- CVE-2026-107223 Excelize is a Go language library for reading and writing Microsoft Excel spreadsheets. vulnerability
Weakness · CWE (1)
- CWE-789 Memory Allocation with Excessive Size Value weakness