Every CVE Search/ Get API key

CVE-2026-107211

Excelize: Unchecked pivot-cache field index in extractPivotTableFields causes unrecoverable panic

8.7 HighFix available

Excelize is a Go language library for reading and writing Microsoft Excel spreadsheets. From 2.8.1 to 2.11.0, separately parsed pivot-table field indices are used to index the pivot-cache field-name slice without bounds checks. extractPivotTableFields uses getPivotCacheFieldsName output while processing GetPivotTables and trusts the dataField fld attribute as an index. When a crafted workbook supplies a pivot-field count mismatch or an out-of-range dataField fld value before GetPivotTables is called, the unchecked index causes a Go slice-bounds panic that escapes the library, allowing an attacker to crash the process or request worker. No fixed version is available as of this review.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
None
Availability
High

Exploit likelihood

0.23%Down 0.1 points since Oct 8, 2026
90%50%10%1%

What each source reports

CVE List Score used 8.7

Excelize: Unchecked pivot-cache field index in extractPivotTableFields causes unrecoverable panic

Excelize is a Go language library for reading and writing Microsoft Excel spreadsheets. From 2.8.1 to 2.11.0, separately parsed pivot-table field indices are used to index the pivot-cache field-name slice without bounds checks. extractPivotTableFields uses getPivotCacheFieldsName output while processing GetPivotTables and trusts the dataField fld attribute as an index. When a crafted workbook supplies a pivot-field count mismatch or an out-of-range dataField fld value before GetPivotTables is called, the unchecked index causes a Go slice-bounds panic that escapes the library, allowing an attacker to crash the process or request worker. No fixed version is available as of this review.

Record
CVE-2026-107211
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-129
Updated
2026-11-02
EUVDEUVD-2026-94526 8.7

Excelize is a Go language library for reading and writing Microsoft Excel spreadsheets. From 2.8.1 to 2.11.0, separately parsed pivot-table field indices are used to index the pivot-cache field-name slice without bounds checks. extractPivotTableFields uses getPivotCacheFieldsName output while processing GetPivotTables and trusts the dataField fld attribute as an index. When a crafted workbook supplies a pivot-field count mismatch or an out-of-range dataField fld value before GetPivotTables is called, the unchecked index causes a Go slice-bounds panic that escapes the library, allowing an attacker to crash the process or request worker. No fixed version is available as of this review.

Record
EUVD-2026-94526
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-mx22-3794-2vpv 8.7

Excelize: Unchecked pivot-cache field index in extractPivotTableFields causes unrecoverable panic

Summary

extractPivotTableFields builds order := pc.getPivotCacheFieldsName() from xl/pivotCache/pivotCacheDefinitionN.xml's <cacheFields> list, then indexes it with values taken from a separately parsed xl/pivotTables/pivotTableN.xml part with zero cross-validation: order[field.Fld] where field.Fld is a raw attacker-controlled int from the <dataField fld="N"> attribute, and order[fieldIdx] where fieldIdx is a loop index over pt.PivotFields.PivotField that need not match the cache's field count. I executed two independent PoCs against the current HEAD: (1) trimmed the pivot cache's <cacheFields> to count=0 while leaving the pivot table's 2 pivotFields untouched -> runtime error: index out of range [0] with length 0 at pivotTable.go:1431; (2) left the 2 cache fields completely intact and only changed one attribute, fld="1" -> fld="99999", in xl/pivotTables/pivotTable1.xml -> runtime error: index out of range [99999] with length 2 at pivotTable.go:1443. Both stack traces confirmed via non-recovered go test runs: extractPivotTableFields -> getPivotTable -> GetPivotTables.

Reachability / who can trigger this

Unauthenticated: any application that opens an untrusted .xlsx containing a pivot table and calls the public File.GetPivotTables(sheet) API. excelize has no recover() anywhere, so this crashes the host process (CLI/worker) or surfaces as an unhandled 500 in a request-scoped-recover HTTP service. Deterministic, single small crafted file, no user interaction beyond the service's normal open-and-read flow.

Proof of Concept / Reproduction

Method:

  1. Verified source at HEAD (commit e81f0500, 2026-09-27, freshly cloned/up to date; git status clean except the new PoC files I added): read pivotTable.go:1425-1454 and confirmed verbatim: order := pc.getPivotCacheFieldsName() (1428), loop for fieldIdx, field := range pt.PivotFields.PivotField indexing order[fieldIdx] at axisRow/axisCol/axisPage (1431/1434/1437), and Data: order[field.Fld] (1443) inside the pt.DataFields.DataField loop -- zero bounds checks anywhere. Confirmed xmlPivotTable.go:271 Fld int xml:"fld,attr"`` on xlsxDataField (raw attacker-controlled int, no validation) and the sibling Fld field at line 252. Ran go build ./... -- compiles clean. Both citations are accurate.
  2. Found the repo already contained an untracked PoC test file from earlier work (pivot_fld_poc_test.go) implementing this exact finding via a byte-level zip-tamper technique (build a legitimate workbook with excelize's own public AddPivotTable API, then hex-edit one raw XML part inside the saved .xlsx's zip bytes -- not a hypothetical reimplementation, uses the real unmodified excelize package). Did not just trust it: ran it myself with go test -run 'TestPivotTableDataFieldFldIndexPanic|TestPivotTableDataFieldFldAttributeOutOfRangePanic' -v . and observed real PASS output with exact matching panic strings.
  3. For stronger, independent evidence beyond a recover-wrapped test, I wrote my own standalone non-test Go program from scratch, cmd/pivotcrash/main.go (module github.com/xuri/excelize/v2, go1.27.0 toolchain), that imports the real compiled excelize package (no reimplementation) with two subcommands: gen/gen-trim (attacker: build a legit pivot-table workbook via the public API, then rezip with one XML part tampered -- either dataField fld="1"->fld="99999", or the pivot cache's <cacheFields count="2"> collapsed to count="0" -- writing the crafted .xlsx to disk) and run (victim: a fresh OS process that does exactly what any consumer service does -- excelize.OpenFile(path) then f.GetPivotTables("Sheet1") -- with zero recover() anywhere in the file or the call chain). Executed as four separate go run process invocations: gen, run, gen-trim, run.

Evidence: Test run (pre-existing PoC file, re-executed by me, both PASS): --- PASS: TestPivotTableDataFieldFldIndexPanic (0.00s) logging `CONFIRMED: GetPivotTables panicked ...…

Record
GHSA-mx22-3794-2vpv
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-129
Updated
2026-11-02
NVD 8.7

Excelize is a Go language library for reading and writing Microsoft Excel spreadsheets. From 2.8.1 to 2.11.0, separately parsed pivot-table field indices are used to index the pivot-cache field-name slice without bounds checks. extractPivotTableFields uses getPivotCacheFieldsName output while processing GetPivotTables and trusts the dataField fld attribute as an index. When a crafted workbook supplies a pivot-field count mismatch or an out-of-range dataField fld value before GetPivotTables is called, the unchecked index causes a Go slice-bounds panic that escapes the library, allowing an attacker to crash the process or request worker. No fixed version is available as of this review.

Record
CVE-2026-107211
CVSS 4.0
8.7 HighCVSS: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
5.5 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-129
Updated
2026-11-02
OSV 8.7

Excelize: Unchecked pivot-cache field index in extractPivotTableFields causes unrecoverable panic

Excelize is a Go language library for reading and writing Microsoft Excel spreadsheets. From 2.8.1 to 2.11.0, separately parsed pivot-table field indices are used to index the pivot-cache field-name slice without bounds checks. extractPivotTableFields uses getPivotCacheFieldsName output while processing GetPivotTables and trusts the dataField fld attribute as an index. When a crafted workbook supplies a pivot-field count mismatch or an out-of-range dataField fld value before GetPivotTables is called, the unchecked index causes a Go slice-bounds panic that escapes the library, allowing an attacker to crash the process or request worker. No fixed version is available as of this review.

Record
CVE-2026-107211
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-129
Updated
2026-11-02
OSVGHSA-mx22-3794-2vpv 8.7

Excelize: Unchecked pivot-cache field index in extractPivotTableFields causes unrecoverable panic

Summary

extractPivotTableFields builds order := pc.getPivotCacheFieldsName() from xl/pivotCache/pivotCacheDefinitionN.xml's <cacheFields> list, then indexes it with values taken from a separately parsed xl/pivotTables/pivotTableN.xml part with zero cross-validation: order[field.Fld] where field.Fld is a raw attacker-controlled int from the <dataField fld="N"> attribute, and order[fieldIdx] where fieldIdx is a loop index over pt.PivotFields.PivotField that need not match the cache's field count. I executed two independent PoCs against the current HEAD: (1) trimmed the pivot cache's <cacheFields> to count=0 while leaving the pivot table's 2 pivotFields untouched -> runtime error: index out of range [0] with length 0 at pivotTable.go:1431; (2) left the 2 cache fields completely intact and only changed one attribute, fld="1" -> fld="99999", in xl/pivotTables/pivotTable1.xml -> runtime error: index out of range [99999] with length 2 at pivotTable.go:1443. Both stack traces confirmed via non-recovered go test runs: extractPivotTableFields -> getPivotTable -> GetPivotTables.

Reachability / who can trigger this

Unauthenticated: any application that opens an untrusted .xlsx containing a pivot table and calls the public File.GetPivotTables(sheet) API. excelize has no recover() anywhere, so this crashes the host process (CLI/worker) or surfaces as an unhandled 500 in a request-scoped-recover HTTP service. Deterministic, single small crafted file, no user interaction beyond the service's normal open-and-read flow.

Proof of Concept / Reproduction

Method:

  1. Verified source at HEAD (commit e81f0500, 2026-09-27, freshly cloned/up to date; git status clean except the new PoC files I added): read pivotTable.go:1425-1454 and confirmed verbatim: order := pc.getPivotCacheFieldsName() (1428), loop for fieldIdx, field := range pt.PivotFields.PivotField indexing order[fieldIdx] at axisRow/axisCol/axisPage (1431/1434/1437), and Data: order[field.Fld] (1443) inside the pt.DataFields.DataField loop -- zero bounds checks anywhere. Confirmed xmlPivotTable.go:271 Fld int xml:"fld,attr"`` on xlsxDataField (raw attacker-controlled int, no validation) and the sibling Fld field at line 252. Ran go build ./... -- compiles clean. Both citations are accurate.
  2. Found the repo already contained an untracked PoC test file from earlier work (pivot_fld_poc_test.go) implementing this exact finding via a byte-level zip-tamper technique (build a legitimate workbook with excelize's own public AddPivotTable API, then hex-edit one raw XML part inside the saved .xlsx's zip bytes -- not a hypothetical reimplementation, uses the real unmodified excelize package). Did not just trust it: ran it myself with go test -run 'TestPivotTableDataFieldFldIndexPanic|TestPivotTableDataFieldFldAttributeOutOfRangePanic' -v . and observed real PASS output with exact matching panic strings.
  3. For stronger, independent evidence beyond a recover-wrapped test, I wrote my own standalone non-test Go program from scratch, cmd/pivotcrash/main.go (module github.com/xuri/excelize/v2, go1.27.0 toolchain), that imports the real compiled excelize package (no reimplementation) with two subcommands: gen/gen-trim (attacker: build a legit pivot-table workbook via the public API, then rezip with one XML part tampered -- either dataField fld="1"->fld="99999", or the pivot cache's <cacheFields count="2"> collapsed to count="0" -- writing the crafted .xlsx to disk) and run (victim: a fresh OS process that does exactly what any consumer service does -- excelize.OpenFile(path) then f.GetPivotTables("Sheet1") -- with zero recover() anywhere in the file or the call chain). Executed as four separate go run process invocations: gen, run, gen-trim, run.

Evidence: Test run (pre-existing PoC file, re-executed by me, both PASS): --- PASS: TestPivotTableDataFieldFldIndexPanic (0.00s) logging `CONFIRMED: GetPivotTables panicked ...…

Record
GHSA-mx22-3794-2vpv
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-129
Updated
2026-11-02
OSVGO-2026-6695 No score

Panic via unchecked pivot-cache field index in github.com/xuri/excelize/v2

Panic via unchecked pivot-cache field index in github.com/xuri/excelize/v2

Record
GO-2026-6695
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
github.com/xuri/excelize/v2
Go
2.8.1 up to 2.11.1-0.20261003002531-6258dcebc4e2
2.11.1-0.20261003002531-6258dcebc4e2

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-107211 is a high vulnerability (CVSS 8.7) in Excelize, published October 7, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.23%, the 14th percentile. Fixed in github.com/xuri/excelize/v2 2.11.1-0.20261003002531-6258dcebc4e2.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open