# XSS via number format code with @ text placeholder bypasses htmlspecialchars in HTML writer ## Vulnerability Overview In PhpSpreadsheet's HTML writer, when a cell contains a custom number format (such as the `@` text placeholder), the formatted data is compared with the original data. If they are equal, the `htmlspecialchars()` escaping is skipped, leading to an XSS vulnerability. ## Affected Versions - **Affected Versions**: - >= 4.0.0, = 3.3.0, = 2.2.0, = 2.0.0, getActiveSheet(); // XSS payload with malicious number format $sheet->setCellValueExplicit('A1', '', DataType::TYPE_STRING); $sheet->getStyle('A1')->getNumberFormat()->setFormatCode('@ '); $writer = new Html($spreadsheet); $writer->save('output.html'); ``` The generated HTML contains: ```html ``` The XSS payload is completely unescaped. ## Tested Bypass Formats | Format Code | Result | Escaped? | |----------|------|--------| | General (default) | Original value | Yes (Secure) | | @ | + value | No (XSS) | | @ (trailing space) | value + | No (XSS) | | x@ | x + value | No (XSS) | Tested and confirmed XSS execution in browsers with PhpSpreadsheet 4.5.0. ## Impact Any application that accepts user-uploaded XLSX files, uses PhpSpreadsheet's HTML writer to convert them to HTML, and displays the HTML to other users is vulnerable to stored XSS attacks. An attacker embeds a payload in a cell of an XLSX file and sets a custom number format.