CVE-2026-59931 Overview
CVE-2026-59931 is a Server-Side Request Forgery (SSRF) vulnerability in PhpSpreadsheet, a widely used pure PHP library for reading and writing spreadsheet files. The flaw resides in the WEBSERVICE() function implemented in Calculation/Web/Service.php. The library validates the initial URL host against a domain whitelist configured through Spreadsheet::setDomainWhiteList(), but PHP's HTTP stream wrapper automatically follows up to 20 HTTP 301/302 redirects without re-validating the destination. An attacker who controls a whitelisted domain, or triggers a redirect from one, can force the server to fetch arbitrary internal or external URLs. The vulnerability is tracked as CWE-918: Server-Side Request Forgery.
Critical Impact
Attackers who can upload XLSX files to affected applications achieve full-read SSRF, exfiltrating up to 32,767 bytes per request from internal services and cloud metadata endpoints such as http://169.254.169.254/.
Affected Products
- PhpSpreadsheet 4.0.0 through 5.8.0
- PhpSpreadsheet 3.3.0 through 3.10.6, 2.2.0 through 2.4.6, and 2.0.0 through 2.1.17
- PhpSpreadsheet releases up to and including 1.30.5
Discovery Timeline
- 2026-07-28 - CVE-2026-59931 published to NVD
- 2026-07-28 - Last updated in NVD database
Technical Details for CVE-2026-59931
Vulnerability Analysis
The webService() method in src/PhpSpreadsheet/Calculation/Web/Service.php performs a one-time host check against the configured whitelist and then invokes file_get_contents($url, false, $ctx) to retrieve the resource. PHP's HTTP stream wrapper follows Location response headers automatically for up to 20 hops. Because the redirect target is never re-validated against the whitelist, an attacker who can cause a whitelisted host to return a 301 or 302 response reaches any URL the PHP process can access. The port component is also not validated, enabling internal port scanning through timing and response-content differentials.
Exploitation returns response bodies as the calculated value of a spreadsheet cell, capped at 32,767 bytes. This yields a full-read SSRF primitive rather than a blind one.
Root Cause
The root cause is missing re-validation of redirect targets combined with PHP's default follow_location=1 behavior on the HTTP stream context. Whitelist enforcement occurs only on the initial URL, so any downstream redirect bypasses the control.
Attack Vector
An attacker uploads a crafted XLSX file containing a WEBSERVICE() formula that references a whitelisted domain configured to redirect to an internal target. When the application invokes getCalculatedValue() on the cell, PhpSpreadsheet fetches the redirected content and stores it in the cell. Practical targets include cloud instance metadata services such as AWS, GCP, and Azure endpoints at http://169.254.169.254/, internal admin services, and arbitrary TCP ports.
// Get results from the webservice
$ctxArray = [
'http' => [
+ 'follow_location' => 0,
'user_agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
],
];
Source: PHPOffice/PhpSpreadsheet commit 7ef7b25. The patch sets follow_location to 0, disabling automatic redirect following in the HTTP stream context so unvalidated hops cannot occur.
Detection Methods for CVE-2026-59931
Indicators of Compromise
- Outbound HTTP requests from application servers to 169.254.169.254, metadata.google.internal, or Azure IMDS endpoints originating from PHP processes.
- Application logs showing WEBSERVICE() formula evaluation followed by requests to internal RFC1918 addresses or non-standard ports.
- Unusual XLSX uploads containing formula cells that reference whitelisted domains hosting redirect endpoints.
Detection Strategies
- Instrument the PhpSpreadsheet host to log all outbound file_get_contents traffic and alert on requests that resolve to link-local, loopback, or private addresses.
- Inspect uploaded spreadsheets for WEBSERVICE( formula strings prior to processing and quarantine files that reference external hosts.
- Correlate application-tier egress with cloud provider IMDS access logs to detect credential retrieval attempts.
Monitoring Recommendations
- Track PhpSpreadsheet library versions across the estate and flag any installation below the fixed releases.
- Monitor for HTTP 301/302 chains terminating at internal addresses on egress proxies.
- Alert on IAM role credential use from unexpected source IPs following any spreadsheet processing event.
How to Mitigate CVE-2026-59931
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.
- Audit application code that calls setDomainWhiteList() and getCalculatedValue() to identify exposure to user-supplied XLSX content.
- Enforce IMDSv2 on AWS workloads and block link-local metadata access at the network layer where feasible.
Patch Information
The fix was released across all supported branches. See the release notes for PhpSpreadsheet 5.8.1, 3.10.7, 2.4.7, 2.1.18, and 1.30.6. The root fix is documented in GHSA-6hq5-7373-42rg and disables automatic redirect following in the HTTP stream context.
Workarounds
- Disable calculation of WEBSERVICE() formulas by not calling getCalculatedValue() on untrusted spreadsheets until upgrade is complete.
- Restrict egress from PhpSpreadsheet hosts to a strict allow-list that excludes cloud metadata endpoints and internal management networks.
- Run the PHP process behind a forward proxy that rejects requests to RFC1918 addresses and link-local ranges.
# Composer upgrade to fixed release
composer require phpoffice/phpspreadsheet:^5.8.1
# Verify installed version
composer show phpoffice/phpspreadsheet | grep versions
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

