GitHub Advisoryadvisory · Packagist
GHSA-j2w7-387v-m2rq PhpSpreadsheet ODS Reader: Unbounded number-rows-repeated → CPU & Memory Exhaustion (DoS)
HIGH
Official page ↗
- Aliases
- CVE-2026-108359
- Ecosystem
- Packagist
- Packages
- phpoffice/phpspreadsheet
- Severity
- High
- CVSS vector
- CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
- Weaknesses
- CWE-400, CWE-789
- Reviewed
- 2026-10-27
Affected packages
• Packagist phpoffice/phpspreadsheet: >= 4.0.0, < 5.10.0 → fixed in 5.10.0
• Packagist phpoffice/phpspreadsheet: >= 3.3.0, < 3.10.8 → fixed in 3.10.8
• Packagist phpoffice/phpspreadsheet: >= 2.2.0, < 2.4.8 → fixed in 2.4.8
• Packagist phpoffice/phpspreadsheet: >= 2.0.0, < 2.1.19 → fixed in 2.1.19
• Packagist phpoffice/phpspreadsheet: < 1.30.7 → fixed in 1.30.7
Description
Summary
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 repeat, unchecked (int) cast
$rowRepeats = (int) $childNode->getAttributeNS($tableNs, 'number-rows-repeated');
...
// line 1151 — row materialisation loop: NO upper bound
for ($rowAdjust = 0; $rowAdjust 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 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: `` (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
1
```
Not vulnerable (for reference - throws exception):
```xml
1
```
This column-repeat example throws `Column string index can not be beyond XFD` exception
(bounded defense, already in place).
Related
Alias · CVE (1)
- CVE-2026-108359 PhpSpreadsheet is a pure PHP library for reading and writing spreadsheet files. vulnerability
References
- https://github.com/PHPOffice/PhpSpreadsheet/security/advisories/GHSA-j2w7-387v-m2rq web
- https://nvd.nist.gov/vuln/detail/CVE-2026-108359 advisory
- https://github.com/PHPOffice/PhpSpreadsheet/commit/299993894dce37aa3b64aa23e9a3f4bb77ab0e66 web
- https://github.com/PHPOffice/PhpSpreadsheet/commit/2de29384aa11223ee08136c0e6a9e9981bc1a2eb web
- https://github.com/PHPOffice/PhpSpreadsheet/commit/980b5c294493856f1a25754f1e8a1d2185b93738 web
- https://github.com/PHPOffice/PhpSpreadsheet/commit/9a0b48622ebfe93fa48cb9bc09ce57303bb07af9 web
- https://github.com/PHPOffice/PhpSpreadsheet/commit/da13f40e8760d599b0e8a296017d4b028b20e86c web
- https://github.com/PHPOffice/PhpSpreadsheet package
- https://github.com/PHPOffice/PhpSpreadsheet/releases/tag/1.30.7 web
- https://github.com/PHPOffice/PhpSpreadsheet/releases/tag/2.1.19 web
- https://github.com/PHPOffice/PhpSpreadsheet/releases/tag/2.4.8 web
- https://github.com/PHPOffice/PhpSpreadsheet/releases/tag/3.10.8 web
- https://github.com/PHPOffice/PhpSpreadsheet/releases/tag/5.10.0 web