GHSA-8MCQ-6WMR-JRJV
Vulnerability from github – Published: 2026-10-07 20:23 – Updated: 2026-10-07 20:23Affected versions and vulnerable location
- Confirmed at
ae2113b(current HEAD). - Sink:
rows.go:967ws.SheetData.Row[rowIdx].C[colNum-1] = *colDatainsidecheckRow. checkRowcomputeslastColfrom the column of the last cell in document order (rows.go:940), allocatestargetListof that length, then re-scatters every source cell intoC[colNum-1].
Root cause
The slice is sized from the last cell's column, but cells are not required to be column-sorted in the XML. A cell that appears earlier in the row but references a higher column than the last cell has colNum-1 >= len(targetList), so the assignment writes out of range. MaxColumns/TotalRows do not help, every individual column is valid; the bug is the ordering assumption, not magnitude.
Attacker model and reachability
Any service that opens an untrusted spreadsheet and calls a worksheet API that goes through workSheetReader -> checkRow (excelize.go:332): GetCellValue, GetCellFormula, CalcCellValue, GetMergeCells, SetCellValue, and essentially every non-streaming worksheet call. (The streaming GetRows/Rows() SAX path does not trigger it.) Unauthenticated, deterministic, unrecovered panic -> process crash.
Proof of concept (executed)
Crafted xl/worksheets/sheet1.xml with a row whose cells are out of column order and whose earlier cell exceeds the last cell's column:
<row r="1"><c r="D1"><v>4</v></c><c r="C1"><v>3</v></c></row>
GetCellValue("Sheet1","A1") (via getCellStringFunc -> workSheetReader -> checkRow) panicked index out of range [3] with length 3 at rows.go:967.
Confirming grep:
rg -n "func checkRow|lastCol|Row\[rowIdx\].C\[colNum-1\]" rows.go
Suggested fix
Size targetList from the maximum cell column in the row (not the last cell in document order), or bounds-check colNum-1 against len(targetList) and grow the slice as needed before the assignment.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/xuri/excelize/v2"
},
"ranges": [
{
"events": [
{
"introduced": "2.0.0"
},
{
"fixed": "2.11.1-0.20260816084418-46a5eb289448"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-107221"
],
"database_specific": {
"cwe_ids": [
"CWE-787"
],
"github_reviewed": true,
"github_reviewed_at": "2026-10-07T20:23:08Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "## Affected versions and vulnerable location\n\n- Confirmed at `ae2113b` (current HEAD).\n- Sink: `rows.go:967` `ws.SheetData.Row[rowIdx].C[colNum-1] = *colData` inside `checkRow`.\n- `checkRow` computes `lastCol` from the column of the last cell in document order (`rows.go:940`), allocates `targetList` of that length, then re-scatters every source cell into `C[colNum-1]`.\n\n## Root cause\n\nThe slice is sized from the last cell\u0027s column, but cells are not required to be column-sorted in the XML. A cell that appears earlier in the row but references a higher column than the last cell has `colNum-1 \u003e= len(targetList)`, so the assignment writes out of range. `MaxColumns`/`TotalRows` do not help, every individual column is valid; the bug is the ordering assumption, not magnitude.\n\n## Attacker model and reachability\n\nAny service that opens an untrusted spreadsheet and calls a worksheet API that goes through `workSheetReader -\u003e checkRow` (`excelize.go:332`): `GetCellValue`, `GetCellFormula`, `CalcCellValue`, `GetMergeCells`, `SetCellValue`, and essentially every non-streaming worksheet call. (The streaming `GetRows`/`Rows()` SAX path does not trigger it.) Unauthenticated, deterministic, unrecovered panic -\u003e process crash.\n\n## Proof of concept (executed)\n\nCrafted `xl/worksheets/sheet1.xml` with a row whose cells are out of column order and whose earlier cell exceeds the last cell\u0027s column:\n\n```xml\n\u003crow r=\"1\"\u003e\u003cc r=\"D1\"\u003e\u003cv\u003e4\u003c/v\u003e\u003c/c\u003e\u003cc r=\"C1\"\u003e\u003cv\u003e3\u003c/v\u003e\u003c/c\u003e\u003c/row\u003e\n```\n\n`GetCellValue(\"Sheet1\",\"A1\")` (via `getCellStringFunc -\u003e workSheetReader -\u003e checkRow`) panicked `index out of range [3] with length 3` at `rows.go:967`.\n\nConfirming grep:\n\n```bash\nrg -n \"func checkRow|lastCol|Row\\[rowIdx\\].C\\[colNum-1\\]\" rows.go\n```\n\n## Suggested fix\n\nSize `targetList` from the maximum cell column in the row (not the last cell in document order), or bounds-check `colNum-1` against `len(targetList)` and grow the slice as needed before the assignment.",
"id": "GHSA-8mcq-6wmr-jrjv",
"modified": "2026-10-07T20:23:08Z",
"published": "2026-10-07T20:23:08Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/qax-os/excelize/security/advisories/GHSA-8mcq-6wmr-jrjv"
},
{
"type": "WEB",
"url": "https://github.com/qax-os/excelize/pull/2376"
},
{
"type": "WEB",
"url": "https://github.com/qax-os/excelize/commit/46a5eb289448e40fbc7d3294589b03861fb822f0"
},
{
"type": "PACKAGE",
"url": "https://github.com/qax-os/excelize"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "Excelize: a row whose earlier cell has a higher column reference than its last cell panics index out of range on almost every worksheet read API"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.