Open actionable advisories and recorded vendor fixes. This public package view has no inventory attached and cannot establish whether your deployment is affected. A vendor fix never resolves your finding; verify your installed version and the source guidance.
Open advisories
12 actionable advisories, newest first. Withdrawn advisories and news are excluded. Coverage is partial.
Go github.com/xuri/excelize/v2 >= 2.8.1, < 2.11.1-0.20261003002531-6258dcebc4e2
Fixed in
2.11.1-0.20261003002531-6258dcebc4e2· Vendor fix available
Issue
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…
Recommended action: Upgrade to 2.11.1-0.20261003002531-6258dcebc4e2 (pre-release) or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Go github.com/xuri/excelize/v2 >= 2.9.0, < 2.11.1-0.20260929015830-8ffeb07ec9a3
Fixed in
2.11.1-0.20260929015830-8ffeb07ec9a3· Vendor fix available
Issue
GetSlicers guards only if ws.ExtLst == nil { return } (slicer.go:816-818) and then immediately dereferences ws.Drawing.RID with no nil check on ws.Drawing itself. Drawing and ExtLst are two independently optional child elements of <worksheet in xl/worksheets/sheetN.xml, populated separately by encoding/xml depending on whether each tag is present. I executed a PoC: took a plain NewFile() workbook (no drawing, no slicer), saved it, then injected a bare <extLst</extLst immediately before </worksheet in xl/worksheets/sheet1.xml (no other change, no drawing element present) and called GetSlicers. Result: runtime error: invalid memory address or nil pointer dereference, confirmed at the ws.Drawing.RID line via stack trace. Reachability / who can trigger this Unauthenticated: any application that opens an untrusted .xlsx and calls the public File.GetSlicers(sheet) API. The trigger is a single empty XML tag with no valid slicer or drawing content required at all, making it an even…
Recommended action: Upgrade to 2.11.1-0.20260929015830-8ffeb07ec9a3 (pre-release) or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Go github.com/xuri/excelize/v2 >= 2.8.1, < 2.11.1-0.20260911060113-ea12859e43c6
Fixed in
2.11.1-0.20260911060113-ea12859e43c6· Vendor fix available
Issue
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 → … →…
Recommended action: Upgrade to 2.11.1-0.20260911060113-ea12859e43c6 (pre-release) or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Go github.com/xuri/excelize/v2 >= 2.10.1, < 2.11.1-0.20260908032718-ecd99d761fe0
Fixed in
2.11.1-0.20260908032718-ecd99d761fe0· Vendor fix available
Issue
leftRight (calc.go:14236) tests the length with countUTF16String, which counts a rune above U+FFFF as 2. The RIGHT branch on 14241 then slices []rune(text) at utf8.RuneCountInString(text)-numChars, which counts it as 1. For text with N such runes the two measures are 2N and N, so any numChars between them passes the guard and gives a negative index. The numChars < 0 check at 14216 does not help, since the value that gets through is positive. What makes it worth reporting is AutoFitColWidth, which evaluates formulas without looking like it does, so normalising an uploaded sheet is enough to reach it. One scoping correction to my own wording there: AutoFitColWidth was added in v2.11.0 and does not exist at v2.10.1, so on v2.10.1 the only reachable path is an explicit CalcCellValue. A 6,077-byte file containing two U+1D7D9 characters in A1 and RIGHT(A1,3) in B1 was created and then opened in a separate program without recovery enabled: So it is a regression, not an old defect. Commit…
Recommended action: Upgrade to 2.11.1-0.20260908032718-ecd99d761fe0 (pre-release) or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Go github.com/xuri/excelize/v2 >= 2.3.1, < 2.11.1-0.20260906004932-2badfcd5841d
Fixed in
2.11.1-0.20260906004932-2badfcd5841d· Vendor fix available
Issue
Opening a file whose first eight bytes are the OLE magic number sends excelize down the decryption path whether or not the caller set a password, or supports encrypted workbooks at all. openReaderAt (excelize.go:198-215) branches on the header alone, and agileDecrypt calls convertPasswdToKey before the verifier hash is checked, so the key-derivation loop runs spinCount times regardless. spinCount (crypt.go:98) is a plain int filled by a bare xml.Unmarshal of the file's own EncryptionInfo stream. Nothing bounds it. A 3072-byte file with spinCount 100000000 makes OpenFile take 58.65s on v2.11.0 with default options, then return zip: not a valid zip file. It is linear at about 0.6 microseconds per iteration and the attacker picks the number, so 1e9 is roughly ten minutes. Nothing on the path takes a context.Context, so the caller cannot cancel it; in an HTTP handler the write timeout returns a response while the goroutine keeps spinning. Memory stays flat at 24 MB, so nothing reclaims…
Recommended action: Upgrade to 2.11.1-0.20260906004932-2badfcd5841d (pre-release) or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Go github.com/xuri/excelize/v2 >= 2.7.1, < 2.11.1-0.20260820023833-99903a3240e5
Fixed in
2.11.1-0.20260820023833-99903a3240e5· Vendor fix available
Issue
A worksheet containing <mergeCell ref=""/ makes mergeCellsParser leave the cached rectangle empty, and cellInRange then indexes that empty slice without a length check. Every non-streaming cell API panics with index out of range [0] with length 0 on the first cell read after opening the file. Where it is cell.go, cellInRange func cellInRange(cell, ref []int) bool { return cell[0] = ref[0] && cell[0] <= ref[2] && cell[1] = ref[1] && cell[1] <= ref[3] } ref is indexed at four positions with no bounds check. The caller that can hand it an empty slice, mergeCellsParser if ref := ws.MergeCells.Cells[i].Ref; len(ws.MergeCells.Cells[i].rect) == 0 && ref != "" { if strings.Count(ref, ":") != 1 { ref += ":" + ref } rect, err := rangeRefToCoordinates(ref) if err != nil { return cell, err } = sortCoordinates(rect) ws.MergeCells.Cells[i].rect = rect } if cellInRange([]int{col, row}, ws.MergeCells.Cells[i].rect) { The ref != "" condition means an empty ref skips the block that populates…
Recommended action: Upgrade to 2.11.1-0.20260820023833-99903a3240e5 (pre-release) or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Go github.com/xuri/excelize/v2 >= 2.0.0, < 2.11.1-0.20260816084418-46a5eb289448
Fixed in
2.11.1-0.20260816084418-46a5eb289448· Vendor fix available
Issue
Affected versions and vulnerable location - Confirmed at ae2113b (current HEAD). - Sink: rows.go:967 ws.SheetData.Row[rowIdx].C[colNum-1] = colData inside checkRow. - 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]. 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…
Recommended action: Upgrade to 2.11.1-0.20260816084418-46a5eb289448 (pre-release) or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Go github.com/xuri/excelize/v2 >= 2.7.0, < 2.11.1-0.20260812075026-be7a16390fa6
Fixed in
2.11.1-0.20260812075026-be7a16390fa6· Vendor fix available
Issue
GetConditionalFormats reads sub-elements of a <cfRule straight out of xl/worksheets/sheetN.xml and indexes them without checking length, and in one case without checking for nil. Three rule types are affected: cellIs, dataBar and colorScale. A workbook with a rule that is missing a child a real Excel file would always have panics the call. Where it is All three sinks are in styles.go, at the same line numbers in v2.11.0 and on master d552a7e. All three are reached from GetConditionalFormats through styles.go:3271. styles.go:3003, in extractCondFmtCellIs: The branch above it handles len(c.Formula) == 2; this one is the fallback and does not check that there is a formula at all, so a cellIs rule with no <formula child indexes an empty slice. styles.go:3132, in the colorScale extractor: c.ColorScale is a xlsxColorScale and is nil when the <cfRule type="colorScale" element has no <colorScale child. Lines 3148 and 3153 then index Cfvo[1] and Cfvo[2] in the three-colour branch with…
Recommended action: Upgrade to 2.11.1-0.20260812075026-be7a16390fa6 (pre-release) or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Go github.com/xuri/excelize/v2 >= 2.1.0, < 2.11.1-0.20260807015645-a54c578af309
Fixed in
2.11.1-0.20260807015645-a54c578af309· Vendor fix available
Issue
The max attribute of a <col 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: column.Min and column.Max are plain int attributes on xmlWorksheet.go:279-280, bound straight from the file. MaxColumns is 16384 (templates.go:176) and nothing in the parse path compares against it. The contrast that makes this an oversight rather than a design decision is inside the callers themselves. SetColWidth validates its own column argument through parseColRange, which clamps to MaxColumns. But flatCols iterates ws.Cols.Col, the file-loaded slice, so the caller's validated…
Recommended action: Upgrade to 2.11.1-0.20260807015645-a54c578af309 (pre-release) or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Go github.com/xuri/excelize/v2 >= 2.1.0, < 2.11.1-0.20260805032953-db93f8d89de7
Fixed in
2.11.1-0.20260805032953-db93f8d89de7· Vendor fix available
Issue
A Zip64 uncompressed-size of 2^63 casts to a negative int64 that bypasses the unzip-size guard and reaches make([]byte, 0, negativeCap) A Zip64 uncompressed-size in the range [2^63, 2^64) casts to a negative int64 in zip.File.FileInfo().Size(), and ReadZipReader does signed arithmetic on that value, so the total-decompression guard is bypassed and the negative size reaches make([]byte, 0, size) in readFile. A 159-byte crafted file panics OpenFile and OpenReader with runtime error: makeslice: cap out of range. The guard, at lib.go:44-46 on HEAD ae2113b: FileInfo().Size() returns int64(UncompressedSize64). UncompressedSize64 is read from the Zip64 extended-information extra record in the central directory and is fully attacker controlled, so any value with the top bit set arrives as a negative int64. unzipSize then goes negative and the comparison against UnzipSizeLimit (default 1000 << 24, templates.go:193) is false no matter how many such entries the archive contains. The…
Recommended action: Upgrade to 2.11.1-0.20260805032953-db93f8d89de7 (pre-release) or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Go github.com/xuri/excelize/v2 >= 2.8.0, < 2.11.1-0.20260731010303-ae2113b410e5
Fixed in
2.11.1-0.20260731010303-ae2113b410e5· Vendor fix available
Issue
File.GetStyle indexes the fill, border and font tables with values taken straight out of xl/styles.xml, and the conditions gating those lookups check only the upper bound. A workbook whose cellXfs entry carries fillId="-1", borderId="-1" or fontId="-1" reaches a negative slice index and panics. excelize has no recover(), so the panic leaves GetStyle and takes the calling process with it. Same defect class as GHSA-48hm-4h8j-58fg, the negative shared-string index, in a different file. That one was fixed by adding the missing lower bound; these three sites still lack it. Where it is styles.go, in GetStyle, lines 1683, 1686 and 1689: The conditions, at lines 1171 to 1185, bound only the top: xf.FillID < len(...) is satisfied by any negative value. FillID, BorderID and FontID are int unmarshalled directly from the fillId, borderId and fontId attributes, so the value is whatever the file says. The border and font conditions have the same shape. The correct pattern is already in the…
Recommended action: Upgrade to 2.11.1-0.20260731010303-ae2113b410e5 (pre-release) or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Unbounded Row Index Allocation in Worksheet Parser (checkSheet OOM/Panic DoS) Summary The checkSheet() function in github.com/xuri/excelize/v2 uses an attacker-controlled <row r="N" XML attribute value directly as the length argument to make([]xlsxRow, row) without validating it against the Excel row limit (TotalRows = 1,048,576). A specially crafted XLSX file can trigger two denial-of-service variants: (A) an out-of-memory process kill when r=2147483647 forces a ~16 GB allocation attempt, and (B) a runtime panic via out-of-bounds slice indexing when r=-1. Any service that opens attacker-supplied XLSX files and calls GetCellValue is affected. No authentication is required. Details The vulnerable code path is triggered by calling GetCellValue (or any API that internally invokes workSheetReader) on an XLSX file containing a crafted worksheet row element. Data flow (source → sink): 1. excelize.go:186-193 — OpenReader reads attacker-controlled spreadsheet bytes. 2. excelize.go:216-223 —…
Recommended action: Upgrade to 2.11.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.