{"schema":"threatline.record/2","record":{"id":"CVE-2026-107214","aliases":["GHSA-2j4c-ffch-9f23","GO-2026-6684"],"summary":"Excelize Decrypt: unrecoverable panics on malformed OLE/CFB encrypted workbooks","details":"### Summary\n\nAny file whose first 8 bytes are the OLE compound-file signature (`D0 CF 11 E0 A1 B1 1A E1`) is routed by `OpenFile`/`OpenReader`/`OpenBytes` → `openReaderAt` → `Decrypt`. The version dispatch only guarantees `len(EncryptionInfo) >= 4` before handing attacker-controlled `EncryptionInfo`/`EncryptedPackage` buffers to `standardDecrypt`/`agileDecrypt`, and no callee validates structure. Malformed but version-valid content therefore fails as an **unrecovered runtime panic** instead of an error, terminating the calling process.\n\n### Details\n\nAll panic classes below were execution-confirmed against pristine master (`ecd99d761fe0`, 2026-09-08). `excelize.go:211-213` maps `Decrypt` *errors* to `ErrWorkbookFileFormat`, but panics bypass that path and kill the process.\n\n| # | Malformed input | Panic | Site |\n|---|---|---|---|\n| 1 | standard, `len(EncryptionInfo)` 4–11 | slice bounds `[:12]` | `crypt.go:238` |\n| 2 | standard, attacker-controlled `headerSize` uint32 | slice bounds `[12:12+headerSize]` / fixed-offset header reads | `crypt.go:238-249` |\n| 3 | standard, verifier remainder < 72 (AES) / 60 (RC4) bytes | slice bounds in `standardEncryptionVerifier` | `crypt.go:282-295` |\n| 4 | standard, `header.KeySize` = 0xFFFFFFFF | slice bounds `[:536870911]` with capacity 48 | `crypt.go:321` |\n| 5 | standard, `EncryptedPackage` stream missing/short | slice bounds `[8:0]` | `crypt.go:268` |\n| 6 | agile, `len(EncryptionInfo)` 4–7 | slice bounds `[8:4]` | `crypt.go:407` |\n| 7 | agile, valid XML without `<keyEncryptors>` | index out of range `[0]` with length 0 | `crypt.go:416`, `433` |\n| 8 | agile, `saltValue` decoded length ≠ AES block | `cipher.NewCBCDecrypter: IV length must equal block size` | `crypt.go:425` → `512` |\n| 9 | any, `keyData blockSize=\"0\"` | integer divide by zero | `crypt.go:539` |\n\nNote the asymmetry pinpointing the missing constraint: the agile path already checks `len(EncryptedPackage) >= 8` (`crypt.go:520-523`) but the standard path does not (#5). Existing tests only cover the error paths (short `<4` bytes → `ErrUnknownEncryptMechanism`, bad XML, base64 errors), never these panic paths.\n\n### PoC\n\nStandalone programs (public API only, inputs built in memory) were provided to the maintainer by email: `1-decrypt-panic` builds seven malformed CFB containers and shows each panic escaping the public `Decrypt` API plus one end-to-end `OpenReader` crash. All cases print PANIC on master and BLOCKED with the proposed patch. A regression guard proves legitimate decryption is unaffected: a workbook encrypted with the package's own `Encrypt()` still opens through the same code path.\n\n(A separate advisory covers the unbounded/negative allocation in `extractPart`.)\n\n### Impact\n\nAny service that calls `OpenFile`/`OpenReader`/`OpenBytes` on untrusted input (upload processing, mail scanning, spreadsheet conversion) can be killed remotely and without authentication by a file of ~100 bytes to ~3 KB. No password is required — panics occur during structural/parameter handling before successful decryption. Site variety means filtering one pattern does not help.\n\n### Proposed fix\n\nA `recover()` boundary in `Decrypt` mapping any panic to `ErrWorkbookFileFormat` (restores the documented error-routing contract; legitimate standard/agile decryption unaffected). A complete patch has been provided to the maintainer; per-site length validation is recommended as defense in depth.","categories":["Libraries & packages"],"product":"github.com/xuri/excelize/v2","vendor":"qax-os","ecosystem":"go","affected_ranges":[{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-2j4c-ffch-9f23","source_modified_at":"2026-10-08T16:31:32Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"go","name":"github.com/xuri/excelize/v2"},"range":">= 2.3.1, < 2.11.1-0.20260915055537-22f76f9acb94"},{"source":"CVE List","source_url":"https://www.cve.org/CVERecord?id=CVE-2026-107214","source_modified_at":"2026-10-07T19:46:20.891Z","fetched_at":"2026-10-23T18:45:31.882637Z","product":"excelize","vendor":"qax-os","versions":[{"version":">= 2.3.1, <= 2.11.0","status":"affected"}],"defaultStatus":null},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-2j4c-ffch-9f23","source_modified_at":"2026-10-19T21:40:56.735377549Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"Go","name":"github.com/xuri/excelize/v2","purl":"pkg:golang/github.com/xuri/excelize/v2"},"ranges":[{"events":[{"introduced":"2.3.1"},{"fixed":"2.11.1-0.20260915055537-22f76f9acb94"}],"type":"SEMVER"}],"versions":[]}],"fixed_versions":[{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-2j4c-ffch-9f23","source_modified_at":"2026-10-08T16:31:32Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"go","name":"github.com/xuri/excelize/v2"},"version":"2.11.1-0.20260915055537-22f76f9acb94"},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-2j4c-ffch-9f23","source_modified_at":"2026-10-19T21:40:56.735377549Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"Go","name":"github.com/xuri/excelize/v2","purl":"pkg:golang/github.com/xuri/excelize/v2"},"version":"2.11.1-0.20260915055537-22f76f9acb94"}],"cvss":7.5,"severity":"High","kev":{"listed":false},"epss":{"probability":0.00244,"percentile":0.1471,"score_date":"2026-10-23"},"published_at":"2026-10-07T17:45:14.274Z","modified_at":"2026-10-19T21:40:56.735377549Z","provenance":[{"source":"GitHub Advisory Database","url":"https://github.com/advisories/GHSA-2j4c-ffch-9f23","fetched_at":"2026-10-23T18:42:43.628194Z","source_modified_at":"2026-10-08T16:31:32Z"},{"source":"CVE List","url":"https://www.cve.org/CVERecord?id=CVE-2026-107214","fetched_at":"2026-10-23T18:45:31.882637Z","source_modified_at":"2026-10-07T19:46:20.891Z"},{"source":"OSV","url":"https://osv.dev/vulnerability/GHSA-2j4c-ffch-9f23","fetched_at":"2026-10-23T18:42:43.628194Z","source_modified_at":"2026-10-19T21:40:56.735377549Z"},{"source":"EPSS","url":"https://api.first.org/data/v1/epss?cve=CVE-2026-107214","fetched_at":"2026-10-23T18:42:43.628194Z","source_modified_at":"2026-10-23"}],"sources":["GitHub Advisory Database","CVE List","OSV","EPSS"],"references":[{"source":"CVE List","url":"https://github.com/qax-os/excelize/security/advisories/GHSA-2j4c-ffch-9f23","tags":["exploit"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-107214","source":"GitHub Advisory Database"},{"source":"CVE List","url":"https://github.com/qax-os/excelize/pull/2395","tags":["x_refsource_MISC"]},{"source":"CVE List","url":"https://github.com/qax-os/excelize/commit/22f76f9acb94b85b3eb9c4365ab4f750cebbc565","tags":["x_refsource_MISC"]},{"url":"https://github.com/advisories/GHSA-2j4c-ffch-9f23","source":"GitHub Advisory Database"}],"locations":[],"motoko_assessment":{"status":"requires_architecture_review","automatic_remediation":false},"cve_state":"PUBLISHED","ssvc":{"exploitation":"poc","automatable":"yes","technical_impact":"partial","assessed_at":"2026-10-07T19:45:56.602078Z"},"classification":{"method":"product-first software-layer rules","rules_version":"2.1","matched_on":"ecosystem","confidence":"heuristic","reviewed":false},"change_timestamp":"2026-10-19T21:40:56.735377549Z","content_hash":"137dfc94d29259906bd763218ea7c461b27f61e8eb39d15fdec3a33f0736fe5c"}}
