CVE-2026-108359
highPriorität · verfolgen · 0EPSS 0.004 · 35. PerzentilUSEPSS · bewertet 2026-10-27
PhpSpreadsheet is a pure PHP library for reading and writing spreadsheet files. Prior to 1.30.7, 2.1.19, 2.4.8, 3.10.8, and 5.10.0, Ods::processTableRow in src/PhpSpreadsheet/Reader/Ods.php accepts an unbounded table:number-rows-repeated attribute from an ODS table row. When the row contains a value, the reader materializes a cell for every repetition without checking the spreadsheet row limit, so a small attacker-controlled ODS file can consume substantial CPU and memory and terminate the PHP worker. Column repetition is separately bounded and is not part of this vulnerability. This issue is fixed in versions 1.30.7, 2.1.19, 2.4.8, 3.10.8, and 5.10.0.
cvss
Technischer Schweregrad, 0–10. Eine Zeile je Quelle.
Basiswert 0–10 · höher = schwerwiegender · Vektor überfahren zum Auflösen⚠ Quellen uneinig · medium–high · 6.6–8.7
schwächen
Die CWE-Schwächeklassen, zu denen dies gehört.
betroffene Produkte (5)
Betroffene Produkte und Versionsbereiche.
Advisories (1)
Hersteller- und Ökosystem-Meldungen dazu.
- GHSA-j2w7-387v-m2rqPhpSpreadsheet ODS Reader: Unbounded number-rows-repeated → CPU & Memory Exhaustion (DoS)2026-10-27ghsa · osvUS
## Summary When PhpSpreadsheet loads an OpenDocument Spreadsheet (`.ods`), `Ods::processTableRow()` reads the `table:number-rows-repeated` attribute of a `<table:table-row>` 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 repeat, unchecked (int) cast $rowRepeats = (int) $childNode->getAttributeNS($tableNs, 'number-rows-repeated'); ... // line 1151 — row materialisation loop: NO upper bound for ($rowAdjust = 0; $rowAdjust < $rowRepeats; ++$rowAdjust) { $rID = $rowID + $rowAdjust; $cell = $spreadsheet->getActiveSheet()->getCell($columnID . $rID); // allocates a Cell $cell->setValueExplicit($dataValue, $type); // ... no bounds check on $rowAdjust or $rID ... } ``` **Why columns are NOT vulnerable (already bounded):** The column-header loop at line 1326 shows the correct pattern with bounds checking: ```php // line 1326 (processTableColumnHeader): BOUNDED correctly for ($rowRepeats2 = $rowRepeats; $rowRepeats2 > 0 && $tableColumnIndex2 <= AddressRange::MAX_COLUMN_INT; --$rowRepeats2) { // HAS BOUNDS CHECK: && $tableColumnIndex2 <= AddressRange::MAX_COLUMN_INT } ``` Additionally, the cell-data column loop at line 1141 calls `getCell()` which throws exception at `Coordinate.php:448` when column exceeds `MAX_COLUMN_INT` (XFD / 16,384): ```php // Coordinate.php line 448 if ($columnIndex > self::MAX_COLUMN_INT) { throw new Exception('Column string index can not be beyond XFD'); } ``` **Result:** Columns are capped at 16,384. Only rows are unbounded. --- ## Impact **Memory exhaustion (single valued cell, repeated many rows):** A non-null cell value with a huge `number-rows-repeated` attribute materialises millions of `Cell` objects → PHP fatal `Allowed memory size ... exhausted`. **Example:** - Payload: `<table:table-row table:number-rows-repeated="5000000">` (5 million rows) - File size: 1.4 KB - Memory consumed: ~256 MB (one Cell object per row) - Result: OOM at default memory limit --- ## Reproduction **Vulnerable payload (causes OOM):** ```xml <table:table table:name="Sheet1"> <table:table-row table:number-rows-repeated="5000000"> <table:table-cell office:value-type="float" office:value="1"> <text:p>1</text:p> </table:table-cell> </table:table-row> </table:table> ``` **Not vulnerable (for reference - throws exception):** ```xml <table:table table:name="Sheet1"> <table:table-row> <table:table-cell office:value-type="float" office:value="1" table:number-columns-repeated="1000000000"> <text:p>1</text:p> </table:table-cell> </table:table-row> </table:table> ``` This column-repeat example throws `Column string index can not be beyond XFD` exception (bounded defense, already in place).
quellen
Welche Quellen diesen Datensatz belegen und wann.
Referenzen (11) nvd
Externe Belege — Patches, Meldungen, Analysen.
- https://github.com/PHPOffice/PhpSpreadsheet/commit/299993894dce37aa3b64aa23e9a3f4bb77ab0e66
- https://github.com/PHPOffice/PhpSpreadsheet/commit/2de29384aa11223ee08136c0e6a9e9981bc1a2eb
- https://github.com/PHPOffice/PhpSpreadsheet/commit/980b5c294493856f1a25754f1e8a1d2185b93738
- https://github.com/PHPOffice/PhpSpreadsheet/commit/9a0b48622ebfe93fa48cb9bc09ce57303bb07af9
- https://github.com/PHPOffice/PhpSpreadsheet/commit/da13f40e8760d599b0e8a296017d4b028b20e86c
- https://github.com/PHPOffice/PhpSpreadsheet/releases/tag/1.30.7
- https://github.com/PHPOffice/PhpSpreadsheet/releases/tag/2.1.19
- https://github.com/PHPOffice/PhpSpreadsheet/releases/tag/2.4.8
Angreifer nutzen Schwachstellen wie diese gegen im Internet exponierte Dienste aus. Sehen Sie mit einem kostenlosen Passiv-Scan, was exponiert ist.
Kostenloser Scan