Home/ Blog/ Security news/ Article
Blog · Security news

PhpSpreadsheet flaw: a tiny malformed file can crash PHP apps that accept spreadsheet uploads (CVE-2026-59933)

CVE-2026-59933: a 1 KB malformed spreadsheet can exhaust memory and crash PHP apps using PhpSpreadsheet, even during automatic file-type detection. Patch now.

Thin ribbon spiraling upward from a small folded document into a tight coil

Most defenses against malicious file uploads assume the danger scales with size: cap the megabytes, reject the oversized archive, move on. A flaw disclosed this week in PhpSpreadsheet, the most widely used PHP library for reading and writing Excel files, breaks that assumption. A malformed file of roughly one kilobyte can drive a PHP process to exhaust all of its memory and die, and it does so during the harmless-sounding step of working out what kind of file it is.

The bug is tracked as CVE-2026-59933 and rated 7.5 on the CVSS scale. It is a denial-of-service issue, not remote code execution or data theft: an attacker cannot run commands or read your data through it. What they can do is crash the worker handling the request, cheaply and repeatedly, with no login and no user interaction. On a busy PHP-FPM pool, a handful of these requests can knock over the workers that serve everyone else.

Why a one-kilobyte file is enough

Old-style .xls files use a container format called OLE, which stores data in numbered sectors linked into chains. PhpSpreadsheet's OLE reader walks those chains using values taken straight from the file, and until this fix it never checked whether a chain looped back on itself. A crafted file can point a sector chain at its own starting sector. The reader then copies the same sector data into memory again and again, in a loop with no exit, until PHP hits its memory limit and the process is killed. The maintainers classify it as both uncontrolled resource consumption (CWE-400) and an infinite loop (CWE-835), which is exactly what the code does.

The fix, shipped across every supported release branch, adds cycle detection, a maximum chain length, bounds checking, and rejection of invalid sector identifiers in OLERead.php. The flaw was reported by Thai Son Dinh of VinSOC Labs. Here is what to upgrade to:

Release branchAffected versionsPatched version
1.x1.30.5 and earlier1.30.6
2.0 to 2.12.0.0 to 2.1.172.1.18
2.2 to 2.42.2.0 to 2.4.62.4.7
3.x3.3.0 to 3.10.63.10.7
4.x to 5.x4.0.0 to 5.8.05.8.1
Source: PHPOffice PhpSpreadsheet security advisory (GHSA-xh5m-36r6-47m3).

If you run any version in the affected column, you are exposed. There is no partial workaround inside the library: the patched releases are the fix.

Your upload size limit will not save you

Two things make this wider than it first looks. First, the malicious file is tiny, so guardrails aimed at oversized uploads never trigger. A one-kilobyte file sails past a size cap set to block ten-megabyte payloads. Second, and more important, the vulnerable code runs during automatic file-type detection. PhpSpreadsheet's IOFactory identifies an unknown upload by asking each reader whether it recognizes the file, and the legacy XLS reader's canRead() check is what trips the flaw. So an application that only ever means to accept modern .xlsx files is still exposed, as long as it lets the library sniff the format instead of pinning the reader explicitly. Many do.

That combination is why a 7.5 availability bug deserves more than a footnote. The exposure is any endpoint where an unauthenticated or low-privilege user can hand your server a spreadsheet: import features, contact and lead uploads, bulk-edit tools, resume forms, invoice parsers. We have seen the same lesson in other widely embedded components this month, from a crafted print job that traps Linux print systems in a processor-burning loop to a single link that can stall millions of Node apps and an OpenSSL flaw that freezes servers by blowing up memory. Cheap, unauthenticated denial of service against a dependency buried three layers down is a recurring pattern, not a one-off.

Patch now, and how to know if you were hit

Upgrade PhpSpreadsheet to the patched release for your branch today; it is the only real fix. Run composer show phpoffice/phpspreadsheet to see what you are actually running, and remember the library is often pulled in as a transitive dependency of an export or reporting package rather than something you required directly.

Because this is a memory-exhaustion bug, an attempt is loud in your logs. Watch for PHP fatal errors of the form "Allowed memory size of N bytes exhausted" with a stack pointing into OLERead.php, and for sudden worker crashes or out-of-memory kills clustered on an upload or import route. A run of those tied to one endpoint and one client is the tell. A managed detection setup that already watches host and application telemetry will surface repeated worker crashes on a single route as an anomaly worth chasing; perimeter file-scanning will miss this entirely, because the file is structurally valid and carries no malicious payload to match.

No public exploit and no in-the-wild abuse have been reported as of this writing, which makes this the good kind of patch: you move before anyone builds the trivial script that turns a one-kilobyte file into an outage. That window rarely stays open long once a resource-exhaustion bug is this easy to trigger.

Frequently asked questions

What is CVE-2026-59933?

CVE-2026-59933 is a denial-of-service flaw in PhpSpreadsheet, a widely used PHP library for reading and writing Excel files. A malformed OLE or XLS file of about one kilobyte can force the OLE reader into an endless loop that exhausts PHP memory and crashes the process. It is rated CVSS 7.5.

Which PhpSpreadsheet versions are affected and fixed?

Affected branches are 1.30.5 and earlier, 2.0.0 to 2.1.17, 2.2.0 to 2.4.6, 3.3.0 to 3.10.6, and 4.0.0 to 5.8.0. The fixes are 1.30.6, 2.1.18, 2.4.7, 3.10.7, and 5.8.1. Upgrade to the release matching your branch.

Can attackers run code or steal data with this flaw?

No. CVE-2026-59933 is availability-only: it can crash the PHP process handling the request but cannot execute code, read files, or access data. The CVSS vector confirms no confidentiality or integrity impact. The practical risk is a cheap, repeatable denial of service against upload endpoints.

Why does limiting upload file size not protect me?

The malicious file is roughly one kilobyte, so caps aimed at large uploads never trigger. The flaw also fires during automatic file-type detection, so even apps that only expect .xlsx files are exposed if they let the library sniff the format. Upgrading is the only reliable fix.

How do I detect exploitation attempts?

Watch for PHP fatal errors reading "Allowed memory size of N bytes exhausted" with a stack trace into OLERead.php, and for worker crashes or out-of-memory kills clustered on an upload or import route. Repeated crashes tied to one endpoint and client are the signature.

Ready to meet the Guardians?

Deploys fast - agentless for monitoring and cloud, a lightweight agent for deep endpoint security. Just Suriq, standing watch.