GHSA-jrfj-fhj2-jjvm: High severity go/github.com/xuri/excelize/v2 vulnerability

Published Oct 7, 2026
·
Updated

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 it either.

v2.5.0 spinCount=10000000 5.307s v2.9.1 spinCount=10000000 5.444s v2.11.0 spinCount=10000000 7.529s v2.11.0 spinCount=100000000 58.654s

The loop arrived with crypt.go in v2.3.1 and is unchanged through v2.11.0.

Excel and LibreOffice write spinCount 100000, which costs 61ms here, so a ceiling well above the legitimate value would cost real files nothing.

This is availability only, and it is not a vulnerability for a program that only opens files its own operator produced.

Affected Software

1 affected componentFixes available
go/github.com/xuri/excelize/v2>=2.3.1<2.11.1-0.20260906004932-2badfcd5841d
2.11.1-0.20260906004932-2badfcd5841d

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade go/github.com/xuri/excelize/v2 to a version that resolves this vulnerability.

    Fixed in 2.11.1-0.20260906004932-2badfcd5841d

Event History

Oct 7, 2026
Advisory Published
via GitHub·08:23 PM
Data Sourced
via GitHub·08:23 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

Does exploitation require the application to support password-protected or encrypted workbooks?

No. A file with the OLE magic number in its first eight bytes enters the decryption path even if the caller did not set a password and does not support encrypted workbooks.

2

Which file-handling scenarios are exposed?

Any service that passes attacker-controlled files to OpenFile is exposed to the attacker-selected key-derivation workload. A 3,072-byte file using spinCount 100000000 caused OpenFile on v2.11.0 with default options to run for 58.65 seconds before returning "zip: not a valid zip file".

3

Can an HTTP timeout or request cancellation stop the work?

No. The affected path does not accept a context.Context, so it cannot be canceled. In an HTTP handler, a write timeout can return a response while the goroutine continues the key-derivation loop.

4

How can this behavior be recognized during investigation?

Look for long-running OpenFile calls on files whose first eight bytes are the OLE magic number, followed by a "zip: not a valid zip file" error. The processing time scales linearly with the file-controlled spinCount, while observed memory usage remained flat at 24 MB.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203