CSIRTS // UNIFIED SECURITY ADVISORY FEEDSYS ● ONLINE · POWERED BY INTELFUSIONS.COM

GHSA-xh5m-36r6-47m3: PHPSpreadsheet: XLS/OLE sector-chain self-loop causes memory exhaustion

highCVSS 7.5CVE-2026-59933
Summary PhpSpreadsheet's OLE reader follows sector chains from attacker-controlled XLS/OLE metadata without detecting cycles or enforcing a maximum chain length. A tiny malformed .xls/OLE file can set the small-block depot sector chain to point back to itself. During normal XLS detection, OLERead::read() appends the same sector data repeatedly until the PHP process exhausts memory. This is reachable from Reader\Xls::canRead() and therefore from automatic spreadsheet type detection. Applications that accept attacker-controlled spreadsheet uploads can suffer denial of service from a very small file. Vulnerability details OLERead::read() loads the input and builds sector chains from attacker-controlled OLE header and allocation-table values: - src/PhpSpreadsheet/Shared/OLERead.php:82 reads the entire file after validating only the OLE magic. - src/PhpSpreadsheet/Shared/OLERead.php:84-97 reads sector-chain metadata from the file header. - src/PhpSpreadsheet/Shared/OLERead.php:132-146 builds bigBlockChain and then follows the small-block depot chain. The vulnerable loop is: $sbdBlock = $this->sbdStartBlock; $this->smallBlockChain = ''; while ($sbdBlock != -2) { $pos = ($sbdBlock + 1) * self::BIG_BLOCK_SIZE; $this->smallBlockChain .= substr($this->data, $pos, 4 * $bbs); $pos += 4 * $bbs; $sbdBlock = self::getInt4d($this->bigBlockChain, $sbdBlock * 4); } There is no visited-sector set, no maximum iteration count, no EOF bound, and no check that the next sector differs from a previously visited sector. If the allocation table maps sector 0 to sector 0, the loop appends the same sector data forever until memory is exhausted. The issue is reachable during normal reader detection/loading: - src/PhpSpreadsheet/Reader/XlsBase.php:153-165 calls OLERead::read() from canRead(). - src/PhpSpreadsheet/Reader/Xls.php:376-383 calls OLERead::read() from loadOLE(). - src/PhpSpreadsheet/IOFactory.php:181-213 calls canRead() while creating a reader for a file, so automatic forma

Details

Source
GitHub Security Advisories (INTL · database · site)
Severity
high — CVSS 7.5
Published
2026-07-23
Last updated
2026-07-23
Exploitation
Not in CISA KEV at last sync

Original advisory: https://github.com/advisories/GHSA-xh5m-36r6-47m3

Exploitation outlook

EPSS (FIRST.org) estimates each CVE’s probability of exploitation in the next 30 days — here is the CSIRTS.com read on those numbers.

Referenced CVEs

CVECSIRTS overviewExternal
CVE-2026-59933coverage & exploitation statusNVD · CVE.org

Same CVEs, other sources

How other CERTs, PSIRTs and databases cover the vulnerabilities in this advisory.

More from GitHub Security Advisories