{"id":"CVE-2026-107224","kind":"vulnerability","aliases":["CVE-2026-107224","GHSA-fw94-4wwp-w8pw","GO-2026-6679"],"related":[],"title":"Excelize: A Zip64 uncompressed-size of 2^63 panics OpenFile/OpenReader","description":"### Summary\n\nA Zip64 uncompressed-size of 2^63 casts to a negative int64 that bypasses the unzip-size guard and reaches make([]byte, 0, negativeCap)\n\nA 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`.\n\nThe guard, at `lib.go:44-46` on HEAD `ae2113b`:\n\n```go\nfileSize := v.FileInfo().Size()\nunzipSize += fileSize\nif unzipSize > f.options.UnzipSizeLimit {\n\treturn fileList, worksheets, newUnzipSizeLimitError(f.options.UnzipSizeLimit)\n}\n```\n\n`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.\n\nThe same negative value also fails the two stream-to-temp checks at `lib.go:53` and `lib.go:64` (`fileSize > f.options.UnzipXMLSizeLimit`), so the entry is not diverted to a temp file and control reaches `readFile`:\n\n```go\n// lib.go:150\ndat := make([]byte, 0, file.FileInfo().Size())\n```\n\n`make` with a negative capacity panics. There is no `recover()` in any non-test file in the library, so the panic leaves the public API and takes down the calling goroutine.\n\nThe asymmetry inside this same function is the clearest way to see it: `unzipToTemp` (`lib.go:83`) handles an entry with a plain `io.Copy` and never pre-allocates from the declared size, so it is indifferent to whatever the header claims. Only the pre-allocating branch trusts that number, and it trusts it after a signed comparison that a wrapped value walks straight through.\n\n## Reproduction, executed against HEAD `ae2113b` (go1.26.5)\n\nA 159-byte archive was built with one stored entry named `xl/worksheets/sheet1.xml`: truthful 1-byte local header, central-directory 32-bit uncompressed size set to the `0xFFFFFFFF` Zip64 sentinel, and a Zip64 extra record (tag `0x0001`, data size 8) declaring `UncompressedSize64 = 0x8000000000000000`.\n\n```\nentry \"xl/worksheets/sheet1.xml\" FileInfo().Size() = -9223372036854775808\nexcelize.OpenReader(bytes.NewReader(raw))  ->  panic: runtime error: makeslice: cap out of range\n```\n\nControl, the identical archive with `UncompressedSize64 = 0x7FFFFFFFFFFFFFFF`:\n\n```\nentry \"xl/worksheets/sheet1.xml\" FileInfo().Size() = 9223372036854775807\nexcelize.OpenReader(bytes.NewReader(raw))  ->  err = \"unzip size exceeds the 16777216000 bytes limit\"\n```\n\nThe control isolates the defect to the sign flip rather than to size magnitude: the guard behaves correctly for any positive declared size and fails only once the value wraps. `archive/zip` itself accepts the archive without complaint, so nothing upstream of excelize rejects it.\n\n## What I verified and what I did not\n\nI ran both cases above myself and confirmed each cited line at HEAD. I caught the panic with a deliberate `recover` in my harness so I could print it; nothing in excelize recovers it, which I checked by grepping every non-test `.go` file. I did not separately run the `OpenFile` variant, since `OpenFile` reaches the same `ReadZipReader` loop, and I did not attempt to turn the bypassed size cap into a separate decompression-bomb primitive.\n\n## Attacker model\n\nAny service that opens a spreadsheet it did not produce. The payload is 159 bytes, needs no authentication, and is deterministic.\n\n## Suggested fix\n\nCompare against the limit in unsigned space, and bound the allocation independently rather than trusting the header:\n\n```go\nif v.UncompressedSize64 > uint64(f.options.UnzipSizeLimit) {\n\treturn fileList, worksheets, newUnzipSizeLimitError(f.options.UnzipSizeLimit)\n}\n```\n\nand in `readFile`, reject or clamp a declared size that is negative or larger than the limit before calling `make`. The same unsigned treatment applies to the two `UnzipXMLSizeLimit` comparisons, which currently route a wrapped size away from the safe streaming path and into the pre-allocating one.","summary":"A crafted XLSX file with a Zip64 uncompressed size of 2^63 makes the Excelize Go library panic when opened with OpenFile or OpenReader. The likely result is a crash of the program that parses the file, a denial of service; the sources do not say whether code execution or data exposure is possible.","severity":"medium","cvss":6.5,"epss":0.00306,"exploited":false,"exploited_at":null,"products":[{"name":"github.com/360EntSecGroup-Skylar/excelize/v2","fixed":[],"affected":">= 2.1.0","ecosystem":"go"},{"name":"github.com/xuri/excelize/v2","fixed":["2.11.1-0.20260805032953-db93f8d89de7"],"affected":"< 2.11.1-0.20260805032953-db93f8d89de7","ecosystem":"go"},{"name":"excelize","fixed":[],"affected":">= 2.1.0, <= 2.11.0","ecosystem":"vendor"},{"name":"github.com/xuri/excelize/v2","fixed":["2.11.1-0.20260805032953-db93f8d89de7"],"affected":">= 2.1.0, < 2.11.1-0.20260805032953-db93f8d89de7","ecosystem":"go"}],"ecosystems":["go","vendor"],"tags":["cwe-190","cwe-681","excelize","go","package","spreadsheet-upload"],"not_affected_if":["trusted-files-only"],"how_to_check":"- Look for `github.com/xuri/excelize/v2` or `github.com/360EntSecGroup-Skylar/excelize/v2` in `go.mod` and check the version.\n- Run `go list -m github.com/xuri/excelize/v2` in the module to see the resolved version.\n- Check whether the program opens untrusted XLSX uploads with OpenFile or OpenReader.","fix":"- `github.com/xuri/excelize/v2` fixed at `2.11.1-0.20260805032953-db93f8d89de7`\n- `github.com/360EntSecGroup-Skylar/excelize/v2`: fixed version unknown","status":"open","published_at":"2026-10-07T19:17:35+00:00","first_seen_at":"2026-11-06T00:09:03+00:00","triaged_at":"2026-11-06T00:10:53+00:00","updated_at":"2026-11-06T00:19:08+00:00","category":"package","confidence":0.6,"triage":{"at":"2026-11-06T00:10:53Z","model":"claude-haiku-5-5","output":{"fix":"- `github.com/xuri/excelize/v2` fixed at `2.11.1-0.20260805032953-db93f8d89de7`\n- `github.com/360EntSecGroup-Skylar/excelize/v2`: fixed version unknown","reach":"unknown","title":"Excelize Go library: crafted Zip64 file makes OpenFile and OpenReader panic","impact":"low","summary":"A crafted XLSX file with a Zip64 uncompressed size of 2^63 makes the Excelize Go library panic when opened with OpenFile or OpenReader. The likely result is a crash of the program that parses the file, a denial of service; the sources do not say whether code execution or data exposure is possible.","audience":"developers","category":"package","nicknames":[],"who_cares":["go","excelize","spreadsheet-upload"],"confidence":0.6,"fix_status":"available","needs_auth":"unknown","worst_case":"Program crashes while opening a crafted spreadsheet file","analyst_note":"Check the GO-2026-6679 page at https://pkg.go.dev/vuln/GO-2026-6679 for the fixed version of the 360EntSecGroup-Skylar import path and whether the panic can be triggered from a remote upload.","how_to_check":"- Look for `github.com/xuri/excelize/v2` or `github.com/360EntSecGroup-Skylar/excelize/v2` in `go.mod` and check the version.\n- Run `go list -m github.com/xuri/excelize/v2` in the module to see the resolved version.\n- Check whether the program opens untrusted XLSX uploads with OpenFile or OpenReader.","plain_action":"","needs_analyst":true,"not_affected_if":["trusted-files-only"],"who_is_affected":"Programs that use the Excelize Go library to open XLSX files, especially files from users or other untrusted sources, are exposed. The sources do not describe a specific configuration; programs that only open trusted, internally generated spreadsheets are less exposed. The sources do not say whether the 360EntSecGroup-Skylar import path has a fixed version.","user_interaction":"unknown","needs_special_setup":"unknown","severity_if_unknown":"low"},"cost_usd":0.000811,"input_tokens":4314,"output_tokens":760,"severity_before":"unknown"},"analyst_status":null,"analyst_note":null,"search":"'-107224':14A,25A '-190':37B '-2026':13A,21A,24A '-46':195C '-6679':22A '-681':39B '-9223372036854775808':465C '/360entsecgroup-skylar/excelize/v2':28A '/xuri/excelize/v2':31A,35A '0':125C,170C,313C '0x0001':454C '0x7fffffffffffffff':483C '0x8000000000000000':460C '0xffffffff':445C '1':431C '1000':261C '159':175C,419C,645C '16777216000':497C '2':8A,56B,107C,135C,137C '24':262C '32':438C '4wwp':18A '63':9A,57B,108C,136C '64':138C '8':457C '9223372036854775807':488C 'accept':532C 'ae2113b':198C,416C 'alloc':374C,392C,665C 'also':279C 'api':341C 'archiv':273C,421C,480C,534C 'archive/zip':530C 'arithmet':151C 'arriv':246C 'asymmetri':349C 'attack':236C,630C 'attempt':616C 'authent':649C 'behav':516C 'bit':244C,439C 'bomb':628C 'bound':663C 'branch':393C 'built':423C 'bypass':115C,162C,620C 'byte':124C,169C,176C,312C,420C,432C,498C,646C 'bytes.newreader':467C,490C 'call':346C 'cap':187C,473C,622C 'capac':320C 'case':555C 'cast':109C,139C 'caught':566C 'central':231C,436C 'central-directori':435C 'check':287C,588C 'cite':561C 'claim':387C 'clearest':356C 'code':93B 'compar':655C 'comparison':257C,404C 'complaint':536C 'confirm':559C 'contain':274C 'control':237C,305C,477C,501C 'correct':517C 'could':578C 'craft':47B,177C 'crash':75B 'cve':12A,23A 'cwe':36B,38B 'dat':310C 'data':96B,455C 'declar':377C,458C,521C 'decompress':159C,627C 'decompression-bomb':626C 'default':260C 'defect':504C 'deliber':571C 'denial':84B 'determinist':652C 'directori':232C,437C 'divert':299C 'entri':271C,296C,365C,427C,461C,484C 'err':492C 'error':185C,471C 'everi':591C 'exceed':495C 'excel':1A,40B,60B,541C,583C 'excelize':32A 'excelize.openreader':466C,489C 'execut':94B,413C 'exposur':97B 'extend':225C 'extended-inform':224C 'extra':227C,451C 'f.options.unzipsizelimit':207C,212C,676C 'f.options.unzipxmlsizelimit':293C 'fail':280C,524C 'fals':265C 'file':49B,82B,178C,303C,331C,596C 'file.fileinfo':314C 'fileinfo':213C,463C,486C 'filelist':209C 'files':200C,204C,292C 'fix':654C 'flip':508C 'fulli':235C 'function':353C 'fw94':17A 'ghsa':16A 'ghsa-fw94-4wwp-w8pw':15A 'github.com':27A,30A,34A 'github.com/360entsecgroup-skylar/excelize/v2':26A 'github.com/xuri/excelize/v2':29A,33A 'go':20A,41B,61B,199C,308C,595C,672C 'go1.26.5':417C 'goe':253C 'goroutin':347C 'grep':590C 'guard':120C,160C,192C,515C 'handl':363C 'har':575C 'head':197C,415C,564C 'header':386C,434C,671C 'ident':479C 'independ':666C 'indiffer':382C 'inform':226C 'insid':350C 'int64':113C,143C,216C,250C 'io.copy':369C 'isol':502C 'leav':338C 'lib.go:150':309C 'lib.go:44':194C 'lib.go:53':289C 'lib.go:64':291C 'lib.go:83':362C 'librari':62B,334C 'like':71B 'limit':499C,658C 'line':562C 'local':433C 'loop':611C 'magnitud':513C 'make':58B,123C,168C,311C,316C 'makeslic':186C,472C 'mani':269C 'matter':267C 'model':631C 'name':428C 'need':647C 'negat':112C,142C,165C,249C,254C,277C,319C 'negativecap':126C 'never':371C 'newunzipsizelimiterror':211C 'non':329C,593C 'non-test':328C,592C 'noth':538C,581C 'number':396C 'one':425C 'open':65B,635C 'openfil':67B,180C,603C,606C 'openfile/openreader':11A 'openread':69B,182C 'packag':42B 'panic':10A,63B,179C,321C,337C,469C,568C 'pars':80B 'payload':643C 'plain':368C 'posit':520C 'possibl':99B 'pre':373C,391C 'pre-alloc':372C,390C 'primit':629C 'print':579C 'produc':641C 'program':78B 'public':340C 'ran':553C 'rang':134C,190C,476C 'rather':509C,667C 'raw':468C,491C 'reach':122C,167C,306C,607C 'read':220C 'readfil':173C,307C 'readzipread':148C,610C 'record':228C,452C 'recov':325C,572C,584C 'reject':542C 'reproduct':412C 'result':72B 'return':208C,215C,677C 'run':601C 'runtim':184C,470C 'say':91B 'see':359C 'sentinel':447C 'separ':600C,625C 'servic':86B,633C 'set':245C,442C 'sign':150C,403C,507C 'sinc':605C 'size':6A,54B,105C,119C,131C,146C,166C,171C,202C,214C,315C,378C,441C,456C,464C,487C,494C,512C,522C,621C 'sourc':88B 'space':661C 'spreadsheet':44B,637C 'spreadsheet-upload':43B 'store':426C 'straight':410C 'stream':284C 'stream-to-temp':283C 'suggest':653C 'summari':100C 'tag':453C 'take':343C 'temp':286C,302C 'templates.go:193':263C 'test':330C,594C 'top':243C 'total':158C 'total-decompress':157C 'trust':394C,399C,669C 'truth':430C 'turn':618C 'two':282C 'uint64':675C 'uncompress':5A,53B,104C,130C,440C 'uncompressed-s':4A,103C,129C 'uncompressedsize64':217C,218C,459C,482C 'unsign':660C 'unzip':118C,493C 'unzip-s':117C 'unzips':203C,206C,251C 'unzipsizelimit':259C 'unziptotemp':361C 'upload':45B 'upstream':539C 'v.fileinfo':201C 'v.uncompressedsize64':674C 'valu':154C,240C,278C,408C,528C 'variant':604C 'verifi':546C 'w8pw':19A 'walk':409C 'way':357C 'whatev':384C 'whether':92B 'without':535C 'worksheet':210C 'wrap':407C,529C 'xl/worksheets/sheet1.xml':429C,462C,485C 'xlsx':48B 'zip.file.fileinfo':145C 'zip64':3A,52B,102C,128C,223C,446C,450C","nicknames":[],"mitigations":[],"who_affected":"Programs that use the Excelize Go library to open XLSX files, especially files from users or other untrusted sources, are exposed. The sources do not describe a specific configuration; programs that only open trusted, internally generated spreadsheets are less exposed. The sources do not say whether the 360EntSecGroup-Skylar import path has a fixed version.","tier":"C","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"developers","plain_action":null,"pkeys":["excelize","githubcom360entsecgroupskylarexcelizev2","githubcomxuriexcelizev2"],"ptokens":["360entsecgroup","com","excelize","github","skylar","v2","xuri"],"labels":["cwe190","cwe681","excelize","go","medium","package","spreadsheetupload","vendor"],"campaign_type":null,"first_public_at":"2026-08-05T03:29:12+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H","cvss_by":"GitHub","poc_count":0,"sources":[{"source":"govuln","external_id":"GO-2026-6679","url":"https://pkg.go.dev/vuln/GO-2026-6679","severity":null,"published_at":"2026-11-05T22:53:46+00:00","modified_at":"2026-11-05T22:53:46+00:00","first_seen_at":"2026-11-06T00:09:03+00:00","fetched_at":"2026-11-06T00:09:03+00:00","note":null},{"source":"nvd","external_id":"CVE-2026-107224","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-107224","severity":null,"published_at":"2026-10-07T19:17:35+00:00","modified_at":"2026-10-13T14:17:32+00:00","first_seen_at":"2026-11-06T00:19:01+00:00","fetched_at":"2026-11-06T00:19:01+00:00","note":null},{"source":"ghsa","external_id":"GHSA-fw94-4wwp-w8pw","url":"https://github.com/advisories/GHSA-fw94-4wwp-w8pw","severity":"medium","published_at":"2026-10-07T20:22:45+00:00","modified_at":"2026-10-07T20:22:47+00:00","first_seen_at":"2026-11-06T00:19:08+00:00","fetched_at":"2026-11-06T00:19:08+00:00","note":null}],"documents":[{"id":81827,"url":"https://github.com/qax-os/excelize/commit/db93f8d89de71589069a54d1b998af02e3c5f7cd","title":"Patch: github.com","kind":"other","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":81828,"url":"https://github.com/qax-os/excelize/pull/2369","title":"Patch: github.com","kind":"other","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":81829,"url":"https://github.com/qax-os/excelize/security/advisories/GHSA-fw94-4wwp-w8pw","title":"Vendor advisory: github.com","kind":"vendor","source":"nvd","publisher":"vendor","text":null,"published_at":"2026-08-05T03:29:12+00:00","relation":"advisory","confidence":null,"note":"Vendor advisory: github.com"},{"id":81918,"url":"https://api.github.com/repos/qax-os/excelize/security-advisories/GHSA-fw94-4wwp-w8pw","title":"Maintainer's advisory: api.github.com","kind":"vendor","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Maintainer's advisory: api.github.com"}],"exploit_sources":[{"type":"epss","score":0.00306,"url":"https://api.first.org/data/v1/epss?cve=CVE-2026-107224"}],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}