Excelize: GetStyle panics on a negative fillId, borderId or fontId in styles.xml
Exact source revision recorded 5 Nov 2026 23:38:32 UTC. It does not establish the source's current position. Latest evidence.
osv · GHSA-5h23-36rv-pm65
Published## Summary `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: ```go xf := s.CellXfs.Xf[idx] if extractStyleCondFuncs["fill"](xf, s) { f.extractFills(s.Fills.Fill[*xf.FillID], s, style) } if extractStyleCondFuncs["border"](xf, s) { f.extractBorders(s.Borders.Border[*xf.BorderID], s, style) } if extractStyleCondFuncs["font"](xf, s) { style.Font = extractFont(s.Fonts.Font[*xf.FontID]) } ``` The conditions, at lines 1171 to 1185, bound only the top: ```go "fill": func(xf xlsxXf, s *xlsxStyleSheet) bool { return (xf.ApplyFill == nil || (xf.ApplyFill != nil && *xf.ApplyFill)) && xf.FillID != nil && s.Fills != nil && *xf.FillID < len(s.Fills.Fill) }, ``` `*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 same function, six lines above at 1677: ```go if idx < 0 || s.CellXfs == nil || len(s.CellXfs.Xf) <= idx { return style, newInvalidStyleID(idx) } ``` and again at 1783. So the style index itself is guarded on both sides while the three ids it leads to are not. ## Proof of concept Executed against `master` at `f98df08`, which is the merge of #2366, so this is current rather than historical. The harness builds a normal styled workbook with excelize, rewrites one attribute of the `cellXfs` entry inside the zip to `-1`, reopens it and calls `GetCellStyle` then `GetStyle`: ``` control (all >= 0) ok style=true err=<nil> fillId=-1 PANIC: runtime error: index out of range [-1] borderId=-1 PANIC: runtime error: index out of range [-1] fontId=-1 PANIC: runtime error: index out of range [-1] ``` The control confirms the harness reads a valid file correctly, so the three panics are the negative ids rather than a broken fixture. Worth mentioning because my first attempt at this harness patched only `fillId` and appeared to show the other two were fine; they are not, the replacement had simply missed them. ## Impact Any application that opens an untrusted `.xlsx` and reads cell styling crashes. `GetStyle` is reached through `GetCellStyle` and from the style-copying and rendering paths, so it sits on the ordinary read path. With no `recover()` anywhere in excelize, a CLI or worker exits and a service returns 500 per request unless the caller installed its own recovery middleware. No memory corruption and no information disclosure. Availability only. ## Suggested fix Add the lower bound to each of the three conditions, matching what line 1677 already does for the style index: ```go *xf.FillID >= 0 && *xf.FillID < len(s.Fills.Fill) ``` and the same for `BorderID` and `FontID`. Three one-line changes in `extractStyleCondFuncs`.
- Source published
- 7 Oct 2026 20:22:39 UTC
- Source modified
- 5 Nov 2026 23:26:03 UTC
- Observed here
- 5 Nov 2026 23:38:32 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_V3 · CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H
Publisher rating · MODERATE