Open actionable advisories and recorded vendor fixes. This public package view has no inventory attached and cannot establish whether your deployment is affected. A vendor fix never resolves your finding; verify your installed version and the source guidance.
Open advisories
15 actionable advisories, newest first. Withdrawn advisories and news are excluded. Coverage is partial.
3.10.82.4.82.1.191.30.75.10.0· Vendor fix available
Issue
PhpSpreadsheet's `Worksheet\Drawing::setPath()` validates an external-image URL against an operator-supplied `isWhitelisted` callback once, on the initial URL only, then fetches it with `file_get_contents()` using a stream context that does not set `follow_location => 0`. A whitelisted host that returns an HTTP `302 Location:` redirect to an internal target is therefore followed by PHP's HTTP wrapper (default `follow_location=1`, `max_redirects=20`) with no re-validation of the redirect hop — defeating the whitelist and yielding a blind SSRF from the server. This is an unfixed variant of CVE-2026-59931 (GHSA-6hq5-7373-42rg, the WEBSERVICE redirect-whitelist-bypass): the `follow_location => 0` fix (commit `7ef7b25e`) was applied ONLY to `Calculation/Web/Service.php`; `Worksheet/Drawing.php` was never touched. Root Cause `src/PhpSpreadsheet/Worksheet/Drawing.php`: - Scheme allowlist at `:125` (`/^(http|https|file|ftp|s3):/`) permits `http`/`https` (the…
Recommended action: Upgrade to 5.10.0, 3.10.8, 2.4.8 or 2 more by release line, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
3.10.82.4.82.1.191.30.75.10.0· Vendor fix available
Issue
When PhpSpreadsheet loads an OpenDocument Spreadsheet (`.ods`), `Ods::processTableRow()` reads the `table:number-rows-repeated` attribute of a ` ` with an unchecked `(int)` cast, then materialises one cell per repeated row. This value is completely unbounded, so a single ~1.4 KB file can instruct the reader to create up to millions of cells, exhausting memory (fatal OOM). No authentication, no special configuration, and the default read filter are required - any application that loads a user-supplied `.ods` is affected. --- Affected versions The `number-rows-repeated` expansion has existed in the ODS reader since its inception (pre-dating the current release branches), so all maintained lines are affected. | Branch | Affected | |--------|----------| | 1.x | ≤ 1.30.6 | | 2.0–2.1 | ≤ 2.1.18 | | 2.2–2.4 | ≤ 2.4.7 | | 3.x | ≤ 3.10.7 | | 4.x–5.x | ≤ 5.9.0 (latest) | --- Root cause (source → sink) `src/PhpSpreadsheet/Reader/Ods.php`: ```php // line 816 — row…
Recommended action: Upgrade to 5.10.0, 3.10.8, 2.4.8 or 2 more by release line, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Recommended action: Upgrade to 5.10.0, 3.10.8, 2.4.8 or 2 more by release line, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The SpreadsheetML XML reader (`Reader\Xml`) scans file content twice through `XmlScanner::scan()`, and each scan runs an `unentity()` callback that calls `html_entity_decode()` after the pattern check. By double-encoding the ` toUtf8($xml); if (preg_match($pattern, $xml)) { // CHECK 2 (UTF-8) throw new Exception('Detected use of ENTITY...'); } if ($this->callback !== null) { $xml = call_user_func($this->callback, $xml); // DECODE (after checks!) } return $xml; // getSecurityScannerOrThrow()->scan($data); // 1st scan // ... $this->fileContents = $data; // stores partially-decoded content ``` 3. `Xml::trySimpleXMLLoadStringPrivate()` (Xml.php, lines 120–150) — re-scans the stored content: ```php $data = $this->fileContents; // already partially decoded $xml = simplexml_load_string( $this->getSecurityScannerOrThrow()->scan($data) // 2nd scan finishes decoding ); ``` The double-scan decode chain: ``` Raw file: <!DOCTYPE | 1st scan(): pattern check → no…
Recommended action: Upgrade to 5.10.0 or 3.10.8 by release line, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
2.1.183.10.72.4.71.30.65.8.1· Vendor fix available
Issue
PhpSpreadsheet's OLE reader follows sector chains from attacker-controlled XLS/OLE metadata without detecting cycles or enforcing a maximum chain length. A tiny malformed .xls/OLE file can set the small-block depot sector chain to point back to itself. During normal XLS detection, OLERead::read() appends the same sector data repeatedly until the PHP process exhausts memory. This is reachable from Reader\Xls::canRead() and therefore from automatic spreadsheet type detection. Applications that accept attacker-controlled spreadsheet uploads can suffer denial of service from a very small file. Vulnerability details OLERead::read() loads the input and builds sector chains from attacker-controlled OLE header and allocation-table values: - src/PhpSpreadsheet/Shared/OLERead.php:82 reads the entire file after validating only the OLE magic. - src/PhpSpreadsheet/Shared/OLERead.php:84-97 reads sector-chain metadata from the file header. - src/PhpSpreadsheet/Shared/OLERead.php:132-146…
Recommended action: Upgrade to 5.8.1, 3.10.7, 2.4.7 or 2 more by release line, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
2.1.183.10.72.4.71.30.65.8.1· Vendor fix available
Issue
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. -…
Recommended action: Upgrade to 5.8.1, 3.10.7, 2.4.7 or 2 more by release line, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
2.1.183.10.72.4.71.30.65.8.1· Vendor fix available
Issue
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 filegetcontents() 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 filegetcontents($url, false, $ctx) to fetch the content. The stream context does not disable redirect following: 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…
Recommended action: Upgrade to 5.8.1, 3.10.7, 2.4.7 or 2 more by release line, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
CVE-2026-34084 was patched by the helper File::prohibitWrappers. The helper calls parseurl($filename, PHPURLSCHEME) and then checks isstring($scheme) && strlen($scheme) 1 to reject stream wrappers such as phar://, php://, data:// or expect://. The check is not equivalent to "does the path contain a wrapper". When the input has the form phar:///path/file.phar/inner with three or more slashes after the scheme, parseurl returns boolean false instead of returning the scheme string. The isstring($scheme) branch is therefore skipped, the helper returns without throwing, and the caller proceeds. PHP's stream layer, however, still treats phar:///... as a valid phar wrapper and opens the underlying phar file. The result is that IOFactory::load($attackerPath) walks past the patch and still touches the phar wrapper. On PHP 7.x, simply reaching the phar wrapper via isfile is enough for PHP to automatically deserialize the phar metadata, which in turn invokes the magic methods wakeup and…
Recommended action: Upgrade to 1.30.5 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
2.4.51.30.43.10.52.1.165.7.0· Vendor fix available
Issue
The XLSX reader's ColumnAndRowAttributes::readRowAttributes() method reads row numbers from XML attributes without validating them against the spreadsheet maximum row limit (AddressRange::MAXROW = 1,048,576). An attacker can craft a minimal XLSX file (~1.6KB) containing a <row r="999999999"/ element that inflates cachedHighestRow to 999,999,999, causing any subsequent row iteration to attempt ~1 billion loop cycles and exhaust CPU resources. Details In src/PhpSpreadsheet/Reader/Xlsx/ColumnAndRowAttributes.php at line 216, the row index is cast directly from XML without bounds checking: This value flows through setRowAttributes() (line 126) → $this-worksheet-getRowDimension($rowNumber) (line 60), which updates the cached highest row in Worksheet.php:1348: The inflated cachedHighestRow is then returned by getHighestRow() (line 1099) and used as the default end bound in RowIterator::resetEnd() (RowIterator.php:86): Notably, column attributes already have equivalent validation at…
Recommended action: Upgrade to 5.7.0, 3.10.5, 2.4.5 or 2 more by release line, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
2.4.53.10.51.30.62.1.165.7.0· Vendor fix available
Issue
The SpreadsheetML XML reader (`Reader\Xml`) does not validate the `ss:Index` row attribute against the maximum allowed row count (`AddressRange::MAX_ROW = 1,048,576`). An attacker can craft a SpreadsheetML XML file with `ss:Index="999999999"` on a ` ` element, which inflates the internal `cachedHighestRow` to ~1 billion. Any subsequent call to `getRowIterator()` without an explicit end row will attempt to iterate ~1 billion rows, causing CPU exhaustion and denial of service. Details In `src/PhpSpreadsheet/Reader/Xml.php`, the `loadSpreadsheetFromFile` method processes ` ` elements: ```php // Xml.php:397-402 if (isset($row_ss['Index'])) { $rowID = (int) $row_ss['Index']; // No validation against MAX_ROW } if (isset($row_ss['Hidden'])) { $rowVisible = ((string) $row_ss['Hidden']) !== '1'; $spreadsheet->getActiveSheet()->getRowDimension($rowID)->setVisible($rowVisible); } ``` The `$rowID` value read from `ss:Index` is cast to int with no upper bound check. It is then…
Recommended action: Upgrade to 5.7.0, 3.10.5, 2.4.5 or 2 more by release line, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
3.10.45.6.01.30.32.1.152.4.4· Vendor fix available
Issue
The usage of isfile, used to verify if the $filename is indeed an actual file, by all(?) Reader implementations (inside the helper function File::assertFile) is php-wrapper aware, for any php wrappers implementing stat(). The 3 wrappers ftp://, phar:// and ssh2.sftp://, all satisfy this requirement - 2 of which are shown in the PoC below. This results in a SSRF, at "best", and RCE at worse. This was tested against the latest release - but the issue seems to go back a while from a first quick check (still present in v1.30.2). PoC To reproduce the vulnerable behavior, the following scripts were used: php.ini file, only needed to build the malicious phar, not necessary to exploit on a deployed instance of the library: makephar.php to create the malicious file: test.php showcases the unsafe pattern: RCE Run the PoC (for RCE): The file /tmp/poc.txt should now be present on disk. Note: the vuln still triggers if the file pointed to inside the phar does not exist/is not supported (html,…
Recommended action: Upgrade to 5.6.0, 3.10.4, 2.4.4 or 2 more by release line, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
2.4.51.30.43.10.52.1.165.7.0· Vendor fix available
Issue
It was discovered that there is a way to bypass HTML escaping in the HTML writer using custom number format codes. The Problem In Writer/Html.php around line 1592, the code checks if the formatted cell data equals the original data to decide whether to apply htmlspecialchars(): When a cell has a custom number format containing @ (text placeholder) with any additional literal characters, the formatter replaces @ with the cell value and adds the extra characters. This makes $cellData !== $origData, so htmlspecialchars() is skipped entirely. Even a single trailing space in the format (@ ) is enough to bypass the escape. Proof of Concept The generated HTML contains: The XSS payload is completely unescaped. Tested Bypass Formats | Format Code | Result | Escaped? | |---|---|---| | General (default) | Original value | YES (safe) | | . @ | . + value | NO (XSS!) | | @ (trailing space) | value + | NO (XSS!) | | x@ | x + value | NO (XSS!) | This was tested with PhpSpreadsheet 4.5.0 and…
Recommended action: Upgrade to 5.7.0, 3.10.5, 2.4.5 or 2 more by release line, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
2.4.51.30.43.10.52.1.165.7.0· Vendor fix available
Issue
The HTML Writer in PhpSpreadsheet bypasses htmlspecialchars() output escaping when a cell uses a custom number format containing the @ text placeholder with additional literal text (e.g., @ "items" or "Total: "@). This allows an attacker to inject arbitrary HTML and JavaScript into the generated HTML output by crafting a malicious XLSX file. Details 1. Conditional escaping in Html.php:1586-1594 htmlspecialchars() is only called when $cellData === $origData (strict comparison). If the formatted output differs from the original value in any way, escaping is skipped entirely. 2. Early return in Formatter.php:136-152 When the format code contains @ with additional literal text (e.g., @ "items"), the formatter substitutes the raw cell value into the format string and returns early — the formatColor callback (which would have applied htmlspecialchars) is never invoked. PoC test.php The produced output contains unescaped data. <img width="719" height="716" alt="Screenshot 2026-04-02…
Recommended action: Upgrade to 5.7.0, 3.10.5, 2.4.5 or 2 more by release line, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
2.4.02.1.121.30.03.10.05.0.0· Vendor fix available
Issue
Product: PhpSpreadsheet Version: 3.8.0 CWE-ID: CWE-918: Server-Side Request Forgery (SSRF) CVSS vector v.3.1: 7.5 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N) CVSS vector v.4.0: 8.7 (AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N) Description: SSRF occurs when a processed HTML document is read and displayed in the browser Impact: Server-Side Request Forgery Vulnerable component: the PhpOffice\PhpSpreadsheet\Worksheet\Drawing class, setPath method Exploitation conditions: getting a string from the user that is passed to the HTML reader Mitigation: improved processing of the $path variable of the setPath method of the PhpOffice\PhpSpreadsheet\Worksheet\Drawing class is needed Researcher: Aleksey Solovev (Positive Technologies) Research The researcher discovered zero-day vulnerability Server-Side Request Forgery (SSRF) (in the setPath method of the PhpOffice\PhpSpreadsheet\Worksheet\Drawing class) in Phpspreadsheet. The latest version (3.8.0) of the phpoffice/phpspreadsheet library was…
Recommended action: Upgrade to 5.0.0, 3.10.0, 2.4.0 or 2 more by release line, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
securityScan() in PHPOffice PhpSpreadsheet through 1.5.0 allows a bypass of protection mechanisms for XXE via UTF-7 encoding in a .xlsx file
Recommended action: Upgrade to 1.5.1 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.