GHSA-wp2g-vpjj-g53r

Suggest an improvement
Source
https://github.com/advisories/GHSA-wp2g-vpjj-g53r
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-wp2g-vpjj-g53r/GHSA-wp2g-vpjj-g53r.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-wp2g-vpjj-g53r
Aliases
Published
2026-10-08T16:31:21Z
Modified
2026-10-08T16:45:19Z
Severity
  • 7.5 (High) CVSS_V3 - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H CVSS Calculator
Summary
Excelize ANCHORARRAY: mutually-referencing array formulas recurse unboundedly via re-entrant CalcCellValue, causing a fatal stack overflow
Details

Summary

ANCHORARRAY (calc.go:15137 on current master) evaluates each cell of the referenced spill range by calling the exported CalcCellValue, which unconditionally constructs a fresh calcContext — fresh entry marker, fresh iterations map, full MaxCalcIterations budget (calc.go:896-900). The circular-reference control only exists within one context: the entry-exclusion marker and per-ref iteration budget are fields of that single context, and completion-based caching (formulaArgCache/calcRawCache) only ever stores results of evaluations that finish.

During a pure cycle no nested evaluation ever finishes, so nothing is ever cached to break the recursion, and each hop re-arms the entire budget. Two ordinary, Excel-legal constructs in an attacker-supplied workbook are enough:

  • A1 (dynamic array formula, ref A1:A1): _xlfn.ANCHORARRAY($B$1)
  • B1 (dynamic array formula, ref B1:B1): _xlfn.ANCHORARRAY($A$1)

→ CalcCellValue → calcCellValue → evalInfixExp → parseReference → cellResolver → … → ANCHORARRAY → CalcCellValue → … forever, ending in a fatal, unrecoverable Go runtime error: runtime: goroutine stack exceeds …-byte limit / fatal error: stack overflow. Go stack overflows cannot be recovered — the whole process aborts.

Details

  • The terminating edge the iterations gate is supposed to provide does not exist across contexts: there is no in-flight tracking shared between nested CalcCellValue calls.
  • Both formulas are ordinary Excel-legal constructs; no exotic XML is required.
  • Excelize's own APIs reach formula evaluation on untrusted cells implicitly (e.g. pivotTable.go:538, picture.go:985/1141, col.go:892), so a service that merely adds a pivot table or a picture over such a workbook dies.
  • No option value prevents it: MaxCalcIterations is irrelevant because every hop gets a fresh budget.
  • Measured: a 64 MB stack budget is exhausted in ~0.09 s; the ~1 GB default in ~1–2 s.

PoC

A standalone program (public API only) was provided to the maintainer by email (4-anchorarray-recursion): NewFile + SetCellFormula with FormulaOpts{Type: array, Ref: A1:A1 / B1:B1}, then CalcCellValue("Sheet1","A1"). On master ecd99d761fe0 (2026-09-08) the process aborts with fatal error: stack overflow; with the proposed patch the cycle terminates normally (CYCLE_TERMINATED) and existing calc tests pass.

Impact

An attacker ships a workbook containing the two formulas; any service that evaluates a formula over those cells — directly via CalcCellValue, or implicitly via AddPivotTable / AddPicture / auto-fit — aborts. Remote, unauthenticated, process-fatal, no configuration prevents it.

Proposed fix

Evaluate spill-range cells through the current calculation context — fn.f.cellResolver(fn.ctx, …) instead of the exported CalcCellValue — so the entry check and iterations gate of the running calculation apply. cellResolver returns the typed value directly (dropping a string round-trip); an ArgEmpty → "" shim preserves the existing ToNumber behavior for empty spill cells, and a fresh-context fallback covers the legacy nil-ctx test paths. A complete patch has been provided to the maintainer.

Database specific
{
    "cwe_ids": [
        "CWE-674"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-10-08T16:31:21Z",
    "nvd_published_at": "2026-10-07T18:17:19Z",
    "severity": "HIGH"
}
References

Affected packages

Go / github.com/xuri/excelize/v2

Package

Name
github.com/xuri/excelize/v2
View open source insights on deps.dev
Purl
pkg:golang/github.com/xuri/excelize/v2

Affected ranges

Type
SEMVER
Events
Introduced
2.8.1
Fixed
2.11.1-0.20260911060113-ea12859e43c6

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-wp2g-vpjj-g53r/GHSA-wp2g-vpjj-g53r.json"