PhpSpreadsheet, XSS, CVE-2026-40296 (Moderate)

Listen to this Post

How CVE-2026-40296 Works:

  1. The vulnerability exists in the HTML Writer component of PhpSpreadsheet.
  2. It allows bypassing HTML escaping using custom number format codes.
  3. The issue is caused by conditional escaping logic in Writer/Html.php.
  4. The function `htmlspecialchars()` is called only if $cellData === $origData.
  5. This strict comparison fails if the formatted output differs from the original value.
  6. When a cell uses a custom number format containing the `@` text placeholder with additional literal text (e.g., @ "items"), the formatter in `Formatter.php` detects it.
  7. The formatter performs an early return, substituting the raw cell value into the format string.
  8. This early return bypasses the `formatColor` callback which would have applied escaping.
  9. Because the cell data is altered by the format substitution, $cellData !== $origData.
  10. Consequently, `htmlspecialchars()` is skipped entirely for that cell.
  11. Even a trailing space in the format code (@) is sufficient to trigger the bypass.
  12. An attacker can inject arbitrary HTML and JavaScript into the generated output.
  13. The attacker crafts a malicious XLSX file with a cell containing a JavaScript payload.
  14. A custom number format like `@ “items”` is applied to that cell.
  15. When the application converts the XLSX to HTML, the payload is rendered unescaped.
  16. The provided Proof of Concept generates a file `output.html` with unescaped code.
  17. The output contains the raw payload directly embedded in the HTML document.
  18. This leads to stored cross-site scripting (XSS) on the target website.
  19. The vulnerability affects all versions of PhpSpreadsheet prior to the patched releases.
  20. It requires no user interaction beyond viewing the converted HTML output.

dailycve form:

Platform: PhpSpreadsheet library
Version: <=5.6.0
Vulnerability : Cross-site scripting
Severity: Moderate
date: 2026-04-28

Prediction: Patch expected 2026-04-28

Analytics under heading What Undercode Say:

Check installed version of PhpSpreadsheet
composer show phpoffice/phpspreadsheet
Locate vulnerable files in the vendor directory
find vendor/phpoffice/phpspreadsheet -name "Html.php" -o -name "Formatter.php"
Search for the conditional escaping condition in Html.php
grep -n "if (\$cellData === \$origData)" vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Html.php
Search for the early return pattern in Formatter.php
grep -n "SYMBOL_AT" vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Formatter.php
Generate a vulnerable HTML output using the PoC
php test.php
Use curl to upload the malicious XLSX file to a vulnerable endpoint
curl -F "[email protected]" http://target.com/upload

Exploit:

An attacker uploads a specially crafted XLSX file. The file contains a cell with the payload `` and a custom number format code containing the `@` text placeholder with additional literal text (e.g., . @). When the application converts the XLSX to HTML using the vulnerable `Html` writer, the payload is embedded directly into the output without HTML escaping, executing arbitrary JavaScript in the victim’s browser.

Protection from this CVE

  • Upgrade PhpSpreadsheet to the patched versions: 1.30.4, 2.1.16, 2.4.5, 3.10.5, or 5.7.0.
  • Apply a fix by modifying `Html.php` to apply `htmlspecialchars()` unconditionally regardless of formatting changes.
  • Escape output after formatting instead of using a conditional comparison with the original data.
  • Use Content Security Policy (CSP) headers to block inline script execution as a defense-in-depth measure.

Impact:

Successful exploitation allows a remote attacker to perform stored cross-site scripting (XSS) attacks. The attacker can inject and execute arbitrary HTML and script code in the user’s browser within the context of the vulnerable website. This can lead to session hijacking, data theft, defacement, or redirection to malicious sites. If the generated HTML is served from a web server, it results in a classic stored XSS scenario; if the file is downloaded and opened locally, the attack vector is more limited but still poses a risk.

🎯Let’s Practice Exploiting & Learn Patching For Free:

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top