Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-59933

CVE-2026-59933: PhpSpreadsheet OLE Reader DoS Vulnerability

CVE-2026-59933 is a denial of service vulnerability in PhpSpreadsheet caused by infinite sector chain loops in the OLE reader. Attackers can exhaust memory with tiny malformed XLS files. This article covers technical details, affected versions, impact, and mitigation.

Published:

CVE-2026-59933 Overview

CVE-2026-59933 is a denial-of-service vulnerability in PhpSpreadsheet, a pure PHP library for reading and writing spreadsheet files. The flaw resides in the OLE reader, which follows sector chains from attacker-controlled XLS/OLE metadata without detecting cycles or enforcing a maximum chain length. A small malformed .xls file can point the small-block depot sector chain back to itself, causing OLERead::read() to append the same sector data repeatedly until PHP exhausts memory. The vulnerability is reachable through automatic spreadsheet type detection via Reader\Xls::canRead(), making any application that accepts spreadsheet uploads a viable target.

Critical Impact

A tiny malformed XLS file can exhaust PHP process memory during automatic file-type detection, causing denial of service on any application that accepts attacker-controlled spreadsheet uploads.

Affected Products

  • PhpSpreadsheet versions 4.0.0 through 5.8.0
  • PhpSpreadsheet versions 3.3.0 through 3.10.6, 2.2.0 through 2.4.6, and 2.0.0 through 2.1.17
  • PhpSpreadsheet all releases up to and including 1.30.5

Discovery Timeline

  • 2026-07-28 - CVE-2026-59933 published to the National Vulnerability Database (NVD)
  • 2026-07-28 - Last updated in NVD database

Technical Details for CVE-2026-59933

Vulnerability Analysis

The vulnerability is classified as uncontrolled resource consumption [CWE-400]. PhpSpreadsheet parses OLE compound document structures used by legacy XLS files. During parsing, the OLE reader walks sector chains referenced by file metadata to reconstruct streams such as the small-block depot.

Because the reader trusts the values it reads without validating them, a sector entry that references itself creates an infinite loop. Each iteration appends the referenced sector data to an in-memory buffer. The process continues until the PHP memory_limit is exceeded and the request terminates.

The issue is reachable from Reader\Xls::canRead(), which participates in automatic reader selection. Applications using IOFactory::load() or IOFactory::createReaderForFile() invoke this detection path even when the user did not explicitly request the XLS reader.

Root Cause

The root cause is missing validation of sector chain integrity in src/PhpSpreadsheet/Shared/OLERead.php. The reader does not track previously visited sectors and does not enforce a maximum chain length. Attacker-controlled metadata therefore dictates the number of loop iterations and the total allocated buffer size.

Attack Vector

An unauthenticated remote attacker uploads a malformed .xls or OLE file to any endpoint that hands the file to PhpSpreadsheet for parsing or type detection. No user interaction beyond the upload is required. The payload can be a few kilobytes in size while triggering allocation of hundreds of megabytes of memory per request.

php
// Security patch in src/PhpSpreadsheet/Shared/OLERead.php
    /** @var mixed[][] */
    private array $props = [];

+    /** @var int[] */
+    private array $possibleLoop = [];
+
    /**
     * Read the file.
     */

Source: PhpSpreadsheet fix commit 85f2556

The patch introduces a $possibleLoop tracking array to detect and break cyclic sector chains before memory is exhausted.

Detection Methods for CVE-2026-59933

Indicators of Compromise

  • PHP-FPM or Apache worker processes terminating with Allowed memory size exhausted errors correlated with spreadsheet upload endpoints.
  • Small .xls uploads (typically under 10 KB) that trigger long request durations or 500-level responses.
  • Repeated failed upload requests from the same source IP targeting endpoints that accept spreadsheets.

Detection Strategies

  • Instrument PHP error logs for Fatal error: Allowed memory size of X bytes exhausted messages originating from OLERead.php or Reader/Xls.php stack frames.
  • Monitor web application logs for anomalous spikes in request duration or memory usage tied to file upload routes.
  • Deploy web application firewall (WAF) rules that flag OLE compound files whose header claims minimal size but contain suspicious SBAT or SAT sector references.

Monitoring Recommendations

  • Track PHP process memory metrics per request and alert when spreadsheet-handling endpoints exceed baseline thresholds.
  • Correlate upload activity with worker crashes using centralized logging to identify probing attempts.
  • Baseline the size distribution of legitimate XLS uploads and alert on outliers with unusually small file size but high processing cost.

How to Mitigate CVE-2026-59933

Immediate Actions Required

  • Upgrade PhpSpreadsheet to a fixed release: 5.8.1, 3.10.7, 2.4.7, 2.1.18, or 1.30.6 depending on your current major version.
  • Audit all application code paths that call IOFactory::load(), IOFactory::createReaderForFile(), or Reader\Xls::canRead() on untrusted input.
  • Restrict PHP memory_limit on upload-handling workers to bound the impact of any remaining resource-exhaustion issues.

Patch Information

The maintainers fixed this issue in PhpSpreadsheet 5.8.1, 3.10.7, 2.4.7, 2.1.18, and 1.30.6. Full remediation details are documented in GitHub Security Advisory GHSA-xh5m-36r6-47m3.

Workarounds

  • Reject .xls and OLE compound files at the application boundary if legacy Excel format support is not required.
  • Enforce a strict maximum upload size and process spreadsheets in an isolated worker with a hard memory cap and short execution timeout.
  • Pre-validate uploaded files with a lightweight OLE parser that enforces sector chain length limits before invoking PhpSpreadsheet.
bash
# Upgrade to the patched release matching your major version
composer require phpoffice/phpspreadsheet:^5.8.1

# Constrain worker resources in php.ini to bound DoS impact
# memory_limit = 128M
# max_execution_time = 30

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.