Public mode

No access to your tenant or devices. Every item links to its source. What this means

Some sources or documents need attention: 275/275 feeds/APIs · 469/469 docs · 9/9 advisories · checked 21:58 UTC Customize Public modeDiscuss ChangeIntel on Discord

Excelize: Streaming GetRows row-bound bypass causes attacker-controlled allocation

Collected exploitation and prediction evidence

Risk source coverage

CISA KEV is observed exploitation evidence. FIRST EPSS is a dated prediction of exploitation in the next 30 days. Missing scores are unknown. This collector requests predictions only for explicit CVE aliases in the public NuGet archive; Microsoft release views retain their existing prediction scope.

No collected risk observation for these identifiers. This does not establish absence of exploitation or a zero probability.

cve-program · CVE-2026-59161

Published

Excelize is a Go language library for reading and writing Microsoft Excel spreadsheets. Prior to 2.11.0, the streaming worksheet reader used by Rows and GetRows does not enforce the TotalRows limit on the row r attribute, allowing a small XLSX file with a row number above 1048576 and no cell coordinate to make GetRows append empty rows up to the attacker-controlled index and consume excessive memory and CPU. This issue is fixed in version 2.11.0.

Source published
10 Jul 2026 15:47:38 UTC
Source modified
14 Jul 2026 01:55:21 UTC
Observed here
23 Oct 2026 15:48:27 UTC
Source terms
CVE Program Terms of Use

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: cve-program · CVE Program Terms of Use. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 4.0 · 8.7 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

euvd · EUVD-2026-42936

Published

Excelize is a Go language library for reading and writing Microsoft Excel spreadsheets. Prior to 2.11.0, the streaming worksheet reader used by Rows and GetRows does not enforce the TotalRows limit on the row r attribute, allowing a small XLSX file with a row number above 1048576 and no cell coordinate to make GetRows append empty rows up to the attacker-controlled index and consume excessive memory and CPU. This issue is fixed in version 2.11.0.

EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON.

Original publisher date fields

datePublished: Jul 10, 2026, 3:47:38 PM

dateUpdated: Jul 14, 2026, 1:55:21 AM

Source published
Jul 10, 2026, 3:47:38 PM (timezone not stated)
Source modified
Jul 14, 2026, 1:55:21 AM (timezone not stated)
Observed here
7 Nov 2026 13:24:44 UTC
Source terms
ENISA EUVD · source terms and attribution apply

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: euvd · ENISA EUVD · source terms and attribution apply. Source text is retained; field grouping and change labels are provided by ChangeIntel.

EUVD CVSS 4.0 · 8.7 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

nvd · CVE-2026-59161

Published

Excelize is a Go language library for reading and writing Microsoft Excel spreadsheets. Prior to 2.11.0, the streaming worksheet reader used by Rows and GetRows does not enforce the TotalRows limit on the row r attribute, allowing a small XLSX file with a row number above 1048576 and no cell coordinate to make GetRows append empty rows up to the attacker-controlled index and consume excessive memory and CPU. This issue is fixed in version 2.11.0.

NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON.

Source analysis status: Analyzed

Weakness classifications: CWE-400 · CWE-770

Original publisher date fields

published: 2026-07-10T17:17:02.250

lastModified: 2026-10-25T15:10:00.147

1 source CPE criteria · context only
  • cpe:2.3:a:excelize:excelize:*:*:*:*:*:go:*:*

The original JSON retains the logical configuration operators, exclusions and version bounds.

Source published
10 Jul 2026 17:17:02 UTC
Source modified
25 Oct 2026 15:10:00 UTC
Observed here
27 Oct 2026 15:15:33 UTC
Source terms
NIST NVD usage terms; underlying source attribution retained

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: nvd · NIST NVD usage terms; underlying source attribution retained. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 4.0 · [email protected] · Secondary · 8.7 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

CVSS 3.1 · [email protected] · Primary · 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

osv · GHSA-q5j5-6p94-4gwc

Published

# Streaming GetRows row-bound bypass causes attacker-controlled allocation ## Summary Excelize's prior row-bound fix for GHSA-h69g / CVE-2026-54063 protects the checked worksheet parser, but the streaming worksheet reader used by `Rows` and `GetRows` does not enforce the same `TotalRows` bound on the row `r` attribute. A small XLSX file can set a row number above Excelize's maximum row (`1048576`) and omit the cell coordinate. `GetRows` then appends empty rows up to the attacker-controlled row index and returns success. This was reproduced on the current default branch commit `1213a8bd7c5ab360554603ac5c995ccaf6eb4314` and the latest release tag `v2.10.1` (`5ad5ab3af0054c55bdce09f1530085600e9f2e45`). ## Affected package - Package: `github.com/xuri/excelize/v2` - Tested affected versions: current default branch at `1213a8bd7c5ab360554603ac5c995ccaf6eb4314`, and release `v2.10.1` - Fixed version: none known at the time of this report ## Impact An attacker who can provide an XLSX file to an application that calls `GetRows` can cause memory and CPU usage to scale with an attacker-controlled row number, even though the file itself is tiny. This is an availability issue and appears to be an incomplete coverage variant of the GHSA-h69g row-index allocation class. In the conservative PoC, `row r="2000000"` returned a `[][]string` with length 2,000,000 and allocated about 46 MB. Larger row numbers scale the allocation further. ## Root cause The checked parser path validates row numbers: - `excelize.go`: `checkRowNum(r int)` rejects negative rows and rows greater than `TotalRows`. - `excelize.go`: `checkSheet()` calls `checkRowNum(r.R)` before allocating sheet rows. - `workSheetReader()` invokes `checkSheet()` / `checkRow()` before returning a cached worksheet. The streaming path does not use that checked parser: - `rows.go`: `Rows(sheet)` opens an XML decoder directly. - `Rows.Next()` accepts the row `r` attribute and assigns it to the iterator's current row without applying `checkRowNum()`. - `Rows.Columns()` also assigns row `r` to the iterator state without applying `checkRowNum()`. - `GetRows()` appends empty row slices for the gap between the previous row and the current row. Because a cell without an `r` coordinate can still contain a value, the worksheet can avoid cell-coordinate row validation while still causing `GetRows()` to materialize rows up to the out-of-range row number. ## Minimal worksheet payload ```xml <?xml version="1.0" encoding="UTF-8"?> <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"> <sheetData> <row r="2000000"><c t="s"><v>0</v></c></row> </sheetData> </worksheet> ``` The workbook also contains a normal `sharedStrings.xml` with one string (`ok`). ## Reproduction A minimal Go harness creates the XLSX in memory and calls `GetRows("Sheet1")`: ```go rows, err := f.GetRows("Sheet1") fmt.Println("rows_len:", len(rows)) if len(rows) > 0 { fmt.Println("last_row:", rows[len(rows)-1]) } fmt.Printf("returned error: %T %v\n", err, err) ``` Observed output on current default branch commit `1213a8bd7c5ab360554603ac5c995ccaf6eb4314`: ```text == streaming GetRows row r=2000000 cell without r == rows_len: 2000000 last_row: [ok] returned error: <nil> <nil> elapsed=21ms alloc_delta=46MB ``` Observed output on latest release tag `v2.10.1`: ```text == streaming GetRows row r=2000000 cell without r == rows_len: 2000000 last_row: [ok] returned error: <nil> <nil> elapsed=14ms alloc_delta=46MB ``` A control using the checked parser with `row r="1048577"` and `c r="A1048577"` correctly returns `row number exceeds maximum limit`, confirming this report is about inconsistent enforcement in the streaming path rather than a missing global constant. ## Expected behavior `Rows` / `GetRows` should reject row numbers greater than `TotalRows` with the same error behavior as the checked parser path. ## Suggested remediation - Apply the same row-bound validation in the streaming reader immediately after parsing a row `r` attribute. - Preserve and return row parsing errors from `GetRows()` instead of silently continuing or returning only `Rows.Close()` errors. - Add regression tests for `GetRows()` on a worksheet containing `row r="1048577"` with a cell value but no cell `r` coordinate.

Source published
10 Sep 2026 15:09:09 UTC
Source modified
17 Sep 2026 17:40:35 UTC
Observed here
24 Oct 2026 13:19:41 UTC
Source terms
GitHub Advisory Database · CC-BY-4.0

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · GitHub Advisory Database · CC-BY-4.0. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS_V4 · CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

Publisher rating · HIGH

osv · GO-2026-6453

Published

In github.com/xuri/excelize/v2, the streaming worksheet reader used by Rows and GetRows does not enforce the maximum row limit (TotalRows) on row "r" attributes. A crafted spreadsheet with an out-of-bounds row index causes GetRows to allocate empty row slices up to the specified row number, leading to excessive memory consumption and denial of service.

Source published
16 Sep 2026 18:00:43 UTC
Source modified
17 Sep 2026 17:30:11 UTC
Observed here
24 Oct 2026 13:19:41 UTC
Source terms
OSV · upstream source license applies

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · OSV · upstream source license applies. Source text is retained; field grouping and change labels are provided by ChangeIntel.

ChangeIntel

An IT change radar: releases, security, known issues, retirements, documentation changes, and service status from public sources. Every item links to supporting evidence; dates and statuses can change after they are read.

Sources read 7 Nov 21:58 UTC · 275 of 275 readable · 273 fully read · documentation 469/469 current