CVE-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
⚡ Watch CVE-2026-59933
Get an email if CVE-2026-59933 is added to CISA KEV, gains public exploit code, or a new advisory cites it — max one per day, one-click unsubscribe.
Exploitation outlook
- Low exploitation risk0.69% 30-day exploitation probability — currently an unlikely target, but scores change as exploit code circulates. Riskier than 49% of all EPSS-scored CVEs.
Advisory coverage (2)
External references
Embed the live status
— this badge updates automatically when the KEV or exploit status changes. How to embed it →
[](https://www.csirts.com/cve/CVE-2026-59933)