{"id":"CVE-2026-107219","aliases":["EUVD-2026-94549","GHSA-jrfj-fhj2-jjvm","GO-2026-6681"],"status":"published","title":"Excelize: Unbounded spinCount in agile decryption burns CPU during OpenFile","description":"Excelize is a Go language library for reading and writing Microsoft Excel spreadsheets. From 2.3.1 to 2.11.0, agile decryption accepts an attacker-controlled spinCount and performs that many password-key derivation iterations before verifier validation. OpenFile reaches agileDecrypt, which passes the unbounded spinCount to convertPasswdToKey before password verification. When a crafted OLE encrypted-workbook header supplies an excessive spinCount and the file is opened, the key-derivation loop performs unbounded attacker-selected work and cannot be cancelled, allowing an attacker to consume a CPU core for an attacker-controlled duration. No fixed version is available as of this review.","severity":{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-12","score":0.00363,"percentile":0.30523,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-400"],"published":"2026-10-07T18:33:34Z","modified":"2026-11-05T23:25:50Z","fixes":[{"ecosystem":"Go","package":"github.com/xuri/excelize/v2","fixed_in":["2.11.1-0.20260906004932-2badfcd5841d"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"Go","package":"github.com/xuri/excelize/v2","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.3.1"},{"fixed":"2.11.1-0.20260906004932-2badfcd5841d"}]}]},{"source":"osv","ecosystem":"Go","package":"github.com/xuri/excelize/v2","ranges":[{"type":"SEMVER","events":[{"introduced":"2.3.1"},{"fixed":"2.11.1-0.20260906004932-2badfcd5841d"}]}]}],"products":[{"vendor":"excelize","product":"excelize"},{"vendor":"qax-os","product":"excelize"}],"references":[{"url":"https://github.com/qax-os/excelize/security/advisories/GHSA-jrfj-fhj2-jjvm","tags":["x_refsource_CONFIRM","Exploit","Vendor Advisory","advisory","web"]},{"url":"https://github.com/qax-os/excelize/pull/2389","tags":["x_refsource_MISC","Issue Tracking","Patch","fix","web"]},{"url":"https://github.com/qax-os/excelize/commit/2badfcd5841d0d88b0ffea119f5a2f3c53b4910b","tags":["x_refsource_MISC","Patch","fix","web"]},{"url":"https://github.com/advisories/GHSA-jrfj-fhj2-jjvm"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/107xxx/CVE-2026-107219.json","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-107219","tags":["advisory"]},{"url":"https://github.com/qax-os/excelize","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-107219","title":"Excelize: Unbounded spinCount in agile decryption burns CPU during OpenFile","description":"Excelize is a Go language library for reading and writing Microsoft Excel spreadsheets. From 2.3.1 to 2.11.0, agile decryption accepts an attacker-controlled spinCount and performs that many password-key derivation iterations before verifier validation. OpenFile reaches agileDecrypt, which passes the unbounded spinCount to convertPasswdToKey before password verification. When a crafted OLE encrypted-workbook header supplies an excessive spinCount and the file is opened, the key-derivation loop performs unbounded attacker-selected work and cannot be cancelled, allowing an attacker to consume a CPU core for an attacker-controlled duration. No fixed version is available as of this review.","status":"published","published":"2026-10-07T18:33:34.46Z","modified":"2026-10-07T19:45:16.819Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high","assessor":"cna"}],"cwes":["CWE-400"],"updated_at":"2026-11-02T13:45:14.072357Z"}],"euvd":[{"id":"EUVD-2026-94549","description":"Excelize is a Go language library for reading and writing Microsoft Excel spreadsheets. From 2.3.1 to 2.11.0, agile decryption accepts an attacker-controlled spinCount and performs that many password-key derivation iterations before verifier validation. OpenFile reaches agileDecrypt, which passes the unbounded spinCount to convertPasswdToKey before password verification. When a crafted OLE encrypted-workbook header supplies an excessive spinCount and the file is opened, the key-derivation loop performs unbounded attacker-selected work and cannot be cancelled, allowing an attacker to consume a CPU core for an attacker-controlled duration. No fixed version is available as of this review.","status":"published","published":"2026-10-07T18:33:34Z","modified":"2026-10-07T19:45:16Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high"}],"updated_at":"2026-11-02T17:27:33.904651Z"}],"ghsa":[{"id":"GHSA-jrfj-fhj2-jjvm","title":"Excelize: Unbounded spinCount in agile decryption burns CPU during OpenFile","description":"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.\n\n`spinCount` (crypt.go:98) is a plain `int` filled by a bare `xml.Unmarshal` of the file's own EncryptionInfo stream. Nothing bounds it.\n\nA 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.\n\n```\nv2.5.0   spinCount=10000000   5.307s\nv2.9.1   spinCount=10000000   5.444s\nv2.11.0  spinCount=10000000   7.529s\nv2.11.0  spinCount=100000000  58.654s\n```\n\nThe loop arrived with `crypt.go` in v2.3.1 and is unchanged through v2.11.0.\n\nExcel and LibreOffice write spinCount 100000, which costs 61ms here, so a ceiling well above the legitimate value would cost real files nothing. \n\nThis is availability only, and it is not a vulnerability for a program that only opens files its own operator produced.","status":"published","published":"2026-10-07T20:23:22Z","modified":"2026-10-07T20:23:23Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high"}],"cwes":["CWE-400"],"updated_at":"2026-11-02T14:41:28.013673Z"}],"nvd":[{"id":"CVE-2026-107219","description":"Excelize is a Go language library for reading and writing Microsoft Excel spreadsheets. From 2.3.1 to 2.11.0, agile decryption accepts an attacker-controlled spinCount and performs that many password-key derivation iterations before verifier validation. OpenFile reaches agileDecrypt, which passes the unbounded spinCount to convertPasswdToKey before password verification. When a crafted OLE encrypted-workbook header supplies an excessive spinCount and the file is opened, the key-derivation loop performs unbounded attacker-selected work and cannot be cancelled, allowing an attacker to consume a CPU core for an attacker-controlled duration. No fixed version is available as of this review.","status":"published","published":"2026-10-07T19:17:34.287Z","modified":"2026-10-13T14:23:15.89Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high","assessor":"secondary"}],"cwes":["CWE-400"],"updated_at":"2026-11-02T14:12:54.809359Z"}],"osv":[{"id":"CVE-2026-107219","title":"Excelize: Unbounded spinCount in agile decryption burns CPU during OpenFile","description":"Excelize is a Go language library for reading and writing Microsoft Excel spreadsheets. From 2.3.1 to 2.11.0, agile decryption accepts an attacker-controlled spinCount and performs that many password-key derivation iterations before verifier validation. OpenFile reaches agileDecrypt, which passes the unbounded spinCount to convertPasswdToKey before password verification. When a crafted OLE encrypted-workbook header supplies an excessive spinCount and the file is opened, the key-derivation loop performs unbounded attacker-selected work and cannot be cancelled, allowing an attacker to consume a CPU core for an attacker-controlled duration. No fixed version is available as of this review.","status":"published","published":"2026-10-07T18:33:34.46Z","modified":"2026-11-05T23:25:50.587459144Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high"}],"cwes":["CWE-400"],"updated_at":"2026-11-06T00:02:13.631839Z"},{"id":"GHSA-jrfj-fhj2-jjvm","title":"Excelize: Unbounded spinCount in agile decryption burns CPU during OpenFile","description":"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.\n\n`spinCount` (crypt.go:98) is a plain `int` filled by a bare `xml.Unmarshal` of the file's own EncryptionInfo stream. Nothing bounds it.\n\nA 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.\n\n```\nv2.5.0   spinCount=10000000   5.307s\nv2.9.1   spinCount=10000000   5.444s\nv2.11.0  spinCount=10000000   7.529s\nv2.11.0  spinCount=100000000  58.654s\n```\n\nThe loop arrived with `crypt.go` in v2.3.1 and is unchanged through v2.11.0.\n\nExcel and LibreOffice write spinCount 100000, which costs 61ms here, so a ceiling well above the legitimate value would cost real files nothing. \n\nThis is availability only, and it is not a vulnerability for a program that only opens files its own operator produced.","status":"published","published":"2026-10-07T20:23:22Z","modified":"2026-11-05T23:25:50.587459144Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high"}],"cwes":["CWE-400"],"updated_at":"2026-11-06T00:02:13.631839Z"}]}}
