CVE-2026-107225

CVE-2026-107225 is a medium-severity improper input validation vulnerability in github.com/xuri/excelize/v2 (go), affecting versions >= 2.8.0, < 2.11.1-0.20260731010303-ae2113b410e5. It is fixed in 2.11.1-0.20260731010303-ae2113b410e5.

Does this CVE actually affect you?

Kodem shows which CVEs are reachable and running in your applications, so you fix what's exploitable, not just what's listed.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Runtime intelligence, not another scanner.

Summary

Excelize: GetStyle panics on a negative fillId, borderId or fontId in styles.xml

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:

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:

"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:

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.

The application does not adequately validate input before processing it, allowing unexpected values to reach sensitive code paths. Typical impact: varies by context: data corruption, logic bypass, or denial of service.

CVE-2026-107225 has a CVSS score of 6.5 (Medium). The vector is network-reachable, no privileges required, and user interaction required. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (2.11.1-0.20260731010303-ae2113b410e5); upgrading removes the vulnerable code path.

Affected versions

github.com/xuri/excelize/v2 (>= 2.8.0, < 2.11.1-0.20260731010303-ae2113b410e5)

Security releases

github.com/xuri/excelize/v2 → 2.11.1-0.20260731010303-ae2113b410e5 (go)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

Already deployed Kodem?

See it in your environmentNew to Kodem? Get a demo →

Remediation advice

Add the lower bound to each of the three conditions, matching what line 1677 already does for the style index:

*xf.FillID >= 0 && *xf.FillID < len(s.Fills.Fill)

and the same for BorderID and FontID. Three one-line changes in extractStyleCondFuncs.

Frequently Asked Questions

  1. What is CVE-2026-107225? CVE-2026-107225 is a medium-severity improper input validation vulnerability in github.com/xuri/excelize/v2 (go), affecting versions >= 2.8.0, < 2.11.1-0.20260731010303-ae2113b410e5. It is fixed in 2.11.1-0.20260731010303-ae2113b410e5. The application does not adequately validate input before processing it, allowing unexpected values to reach sensitive code paths.
  2. How severe is CVE-2026-107225? CVE-2026-107225 has a CVSS score of 6.5 (Medium). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
  3. Which versions of github.com/xuri/excelize/v2 are affected by CVE-2026-107225? github.com/xuri/excelize/v2 (go) versions >= 2.8.0, < 2.11.1-0.20260731010303-ae2113b410e5 is affected.
  4. Is there a fix for CVE-2026-107225? Yes. CVE-2026-107225 is fixed in 2.11.1-0.20260731010303-ae2113b410e5. Upgrade to this version or later.
  5. Is CVE-2026-107225 exploitable, and should I be worried? Whether CVE-2026-107225 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  6. What actually determines whether CVE-2026-107225 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  7. How do I fix CVE-2026-107225? Upgrade github.com/xuri/excelize/v2 to 2.11.1-0.20260731010303-ae2113b410e5 or later.

Other vulnerabilities in github.com/xuri/excelize/v2

Stop the waste.
Protect your environment with Kodem.