GHSA-6hq5-7373-42rg: PHPSpreadsheet: SSRF bypass via HTTP redirect in WEBSERVICE() domain whitelist
Summary
The domain whitelist introduced in PhpSpreadsheet 5.4.0 for the WEBSERVICE() formula function can be bypassed via HTTP redirect. The whitelist validates only the initial URL's hostname, but file_get_contents() follows 302/301 redirects by default without re-validating the redirect target against the whitelist. This allows an attacker to reach internal services through a whitelisted domain that issues an HTTP redirect.
Details
In Calculation/Web/Service.php, the webService() method validates the URL's host against a domain whitelist set via Spreadsheet::setDomainWhiteList(). If the host passes validation, the method calls file_get_contents($url, false, $ctx) to fetch the content.
The stream context does not disable redirect following:
$ctxArray = [
'http' => [
'user_agent' => 'Mozilla/5.0 ...',
// follow_location defaults to true
// max_redirects defaults to 20
],
];
PHP's HTTP stream wrapper follows redirects automatically (up to 20 hops by default). The redirect target URL is not re-validated against the domain whitelist. An attacker who can trigger a 302 redirect from a whitelisted domain can redirect the request to any arbitrary URL, including internal network addresses.
Vulnerable code (Calculation/Web/Service.php):
// Whitelist check — runs ONCE on the initial URL
$domainWhiteList = $cell?->getWorksheet()->getParent()?->getDomainWhiteList() ?? [];
$host = $parsed['host'] ?? '';
if (!in_array($host, $domainWhiteList, true)) {
return ($cell === null) ? null : Functions::NOT_YET_IMPLEMENTED;
}
// HTTP request — follows redirects to ANY destination
$ctx = stream_context_create($ctxArray);
$output = @file_get_contents($url, false, $ctx);
Additionally, the whitelist check uses only the hostname from parse_url(), ignoring the port. This means whitelisting example.com permits access to all ports on that host.
PoC
Prerequisites:
- Application uses PhpSpreadsheet >= 5.4.0
- Application calls $spreadsheet->setDomainWhiteList([...]) with at least one do
Details
Original advisory: https://github.com/advisories/GHSA-6hq5-7373-42rg
Exploitation outlook
EPSS (FIRST.org) estimates each CVE’s probability of exploitation in the next 30 days — here is the CSIRTS.com read on those numbers.
- Low exploitation riskCVE-2026-599310.53% 30-day exploitation probability — currently an unlikely target, but scores change as exploit code circulates. Riskier than 42% of all scored CVEs.
Referenced CVEs
| CVE | CSIRTS overview | External |
|---|---|---|
| CVE-2026-59931 | coverage & exploitation status | NVD · CVE.org |
Same CVEs, other sources
How other CERTs, PSIRTs and databases cover the vulnerabilities in this advisory.
More from GitHub Security Advisories
- mediumGHSA-jr6p-8pjj-mfx6: Capsule has an incomplete fix of CVE-2026-22872: TenantResource RawItems and Generators s…2026-07-31
- mediumGHSA-68cj-mvg9-rgm2: Capsule: CapsuleConfiguration NodeMetadata regex fields lack webhook validation, allowing…2026-07-31
- mediumGHSA-ff84-5f28-78qj: re2: Out-of-bounds heap read in `exec`/`test`/`match` via attacker-influenced `lastIndex`…2026-07-31
- mediumGHSA-6hxr-mr5r-9836: re2: Global `String.prototype.match` with an empty-matchable pattern never advances → inf…2026-07-31
- mediumGHSA-x83g-979r-f5fh: Sylius Mollie Plugin has unauthenticated IDOR that leaks order token and customer PII2026-07-31