CVE-2026-40296 Overview
CVE-2026-40296 is a stored cross-site scripting (XSS) vulnerability in PhpSpreadsheet, a pure PHP library for reading and writing spreadsheet files. The HTML writer skips htmlspecialchars escaping when a cell's formatted value differs from its original value. Attackers who control both the cell value and the cell number format in an uploaded spreadsheet can inject malicious HTML or JavaScript. When the spreadsheet is later converted to HTML and rendered for other users, the payload executes in their browsers. The issue is fixed in versions 5.7.0, 3.10.5, 2.4.5, 2.1.16, and 1.30.4.
Critical Impact
Authenticated attackers can deliver stored XSS to any user who views an HTML-rendered spreadsheet, enabling session theft, account takeover, and arbitrary actions in the victim's browser context.
Affected Products
- PhpSpreadsheet versions prior to 5.7.0 on the 5.x branch
- PhpSpreadsheet versions prior to 3.10.5, 2.4.5, and 2.1.16 on the 3.x and 2.x branches
- PhpSpreadsheet versions prior to 1.30.4 on the 1.x branch
Discovery Timeline
- 2026-05-06 - CVE-2026-40296 published to NVD
- 2026-05-06 - Last updated in NVD database
Technical Details for CVE-2026-40296
Vulnerability Analysis
The vulnerability is classified as Cross-Site Scripting [CWE-79]. PhpSpreadsheet's HTML writer renders cell content into HTML output. When the writer detects that a cell's formatted value matches its original value, it applies htmlspecialchars to neutralize HTML metacharacters. When the formatted value differs from the original value, the writer assumes the formatter has already produced safe output and emits the formatted string directly.
This assumption breaks for number formats containing the text placeholder @ combined with literal characters. Formats such as ". @", "@ ", or "x@" instruct the formatter to substitute the cell value for @ and append the surrounding literals. The resulting formatted string differs from the original cell value, so escaping is bypassed and any HTML or script tags in the cell value reach the rendered page unchanged.
Root Cause
The root cause is an unsafe trust boundary in the HTML writer's escaping logic. Output sanitization is conditional on value equality rather than always applied. Any formatter transformation, including benign ones like literal concatenation, disables escaping. The writer treats formatter output as a sanitized string when it is in fact attacker-controllable user data.
Attack Vector
Exploitation requires an attacker who can supply both a cell value and a number format on a spreadsheet that the application later converts to HTML for other users. The attacker sets the cell value to an XSS payload such as a <script> or <img onerror=...> tag. The attacker assigns a number format that contains @ plus at least one literal character, forcing the formatted output to differ from the raw value. When a victim views the rendered HTML, the payload executes in the victim's session context.
The vulnerability requires user interaction and low privileges, and the scope changes because the injected script runs in the rendering application's origin rather than the uploader's. See the GitHub Security Advisory for the maintainer's technical write-up.
Detection Methods for CVE-2026-40296
Indicators of Compromise
- Spreadsheet files containing cells whose number format strings include @ followed by or preceded by literal characters such as . @, @ , or x@.
- Cell values containing HTML tag fragments such as <script, onerror=, onload=, javascript:, or <img inside uploaded XLSX, ODS, or XLS files.
- HTML output produced by PhpSpreadsheet that contains unescaped < or > characters originating from spreadsheet cell content.
Detection Strategies
- Audit application logs for spreadsheet uploads followed by HTML conversion calls, and inspect the rendered output for raw HTML markup that should have been escaped.
- Statically scan uploaded spreadsheets to flag cells where the number format token list contains @ combined with non-@ literal characters.
- Review web server response bodies for unescaped script-like content within elements emitted by PhpSpreadsheet's HTML writer.
Monitoring Recommendations
- Monitor for browser-side Content Security Policy (CSP) violations on pages that render spreadsheet content.
- Track outbound requests from rendered spreadsheet pages to unexpected domains, indicating data exfiltration via injected script.
- Alert on PhpSpreadsheet library versions in production deployments that are below the fixed releases listed in the advisory.
How to Mitigate CVE-2026-40296
Immediate Actions Required
- Upgrade PhpSpreadsheet to 5.7.0, 3.10.5, 2.4.5, 2.1.16, or 1.30.4 depending on the branch in use.
- Inventory all applications using PhpSpreadsheet and confirm the installed version through composer show phpoffice/phpspreadsheet.
- Apply a strict Content Security Policy that disallows inline scripts on pages rendering converted spreadsheet content.
Patch Information
The maintainers fixed the issue in PhpSpreadsheet versions 5.7.0, 3.10.5, 2.4.5, 2.1.16, and 1.30.4. The fix ensures htmlspecialchars escaping is applied to cell content regardless of whether the formatted value differs from the original value. Patch details are available in the GitHub Security Advisory GHSA-hrmw-qprp-wgmc.
Workarounds
- Strip or normalize cell number formats in uploaded spreadsheets before invoking the HTML writer, removing any format containing the @ text placeholder.
- Post-process HTML writer output through a server-side HTML sanitizer such as HTML Purifier before serving it to users.
- Restrict spreadsheet upload privileges to trusted users until upgrading to a fixed version.
# Upgrade to a patched PhpSpreadsheet release via Composer
composer require phpoffice/phpspreadsheet:^5.7.0
# Verify installed version
composer show phpoffice/phpspreadsheet | grep versions
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


