CVE-2024-55878
Description
SimpleXLSX is software for parsing and retrieving data from Excel XLSx files. Starting in version 1.0.12 and prior to version 1.1.12, when calling the extended toHTMLEx method, it is possible to execute arbitrary JavaScript code. Version 1.1.12 fixes the issue. As a workaround, don't use direct publication via toHTMLEx.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
A stored XSS vulnerability in SimpleXLSX's toHTMLEx method allows arbitrary JavaScript execution, fixed in version 1.1.12.
SimpleXLSX is a PHP library for parsing Excel XLSx files. In versions 1.0.12 through 1.1.12, the toHTMLEx method does not properly sanitize output, allowing injection of arbitrary JavaScript code. This is a classic case of insufficient output encoding, leading to cross-site scripting (XSS) vulnerabilities [1].
An attacker can craft a malicious XLSx file containing JavaScript payloads in cell data. When the library processes this file and outputs HTML via the toHTMLEx method, the JavaScript executes in the browser of any user viewing the output. No authentication is required beyond the ability to supply the file to the processing script [1].
Successful exploitation allows the attacker to execute arbitrary scripts in the context of the user's session. This can lead to theft of cookies, session tokens, or other sensitive information; redirection to malicious sites; or performing actions on behalf of the user without their consent [1].
The issue is fixed in SimpleXLSX version 1.1.12. Users should upgrade immediately. As a workaround, avoid using the toHTMLEx method for direct publication until the upgrade can be performed [1].
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
shuchkin/simplexlsxPackagist | >= 1.0.12, < 1.1.12 | 1.1.12 |
Affected products
31.0.12, 1.0.13, 1.0.14, …+ 1 more
- (no CPE)range: 1.0.12, 1.0.13, 1.0.14, …
- (no CPE)range: >=1.0.12, <1.1.12
Patches
20044a4c917031 file changed · +16 −14
src/SimpleXLSXEx.php+16 −14 modified@@ -129,9 +129,9 @@ public function readThemeColors() foreach ($colors12 as $c) { $v = $this->xlsx->theme->themeElements->clrScheme->{$c}; if (isset($v->sysClr)) { - $this->themeColors[] = (string) $v->sysClr['lastClr']; + $this->themeColors[] = substr((string) $v->sysClr['lastClr'], 0, 6); } elseif (isset($v->srgbClr)) { - $this->themeColors[] = (string) $v->srgbClr['val']; + $this->themeColors[] = substr((string) $v->srgbClr['val'], 0, 6); } else { $this->themeColors[] = null; } @@ -148,7 +148,7 @@ public function readFonts() foreach ($this->xlsx->styles->fonts->font as $v) { $u = ''; if (isset($v->u)) { - $u = isset($v->u['val']) ? (string) $v->u['val'] : 'single'; + $u = isset($v->u['val']) ? htmlspecialchars((string) $v->u['val'], ENT_QUOTES) : 'single'; } $f = [ 'b' => isset($v->b) && ($v->b['val'] === null || $v->b['val']), @@ -157,10 +157,10 @@ public function readFonts() 'strike' => isset($v->strike) && ($v->strike['val'] === null || $v->strike['val']), 'sz' => isset($v->sz['val']) ? (int) $v->sz['val'] : 11, 'color' => $this->getColorValue($v->color), - 'name' => isset($v->name['val']) ? (string) $v->name['val'] : 'Calibri', + 'name' => isset($v->name['val']) ? htmlspecialchars((string) $v->name['val'], ENT_QUOTES) : 'Calibri', 'family' => isset($v->family['val']) ? (int) $v->family['val'] : 2, 'charset' => isset($v->charset['val']) ? (int) $v->charset['val'] : 1, - 'scheme' => isset($v->scheme['val']) ? (string) $v->scheme['val'] : 'minor' + 'scheme' => isset($v->scheme['val']) ? htmlspecialchars((string) $v->scheme['val'], ENT_QUOTES) : 'minor' ]; $this->fonts[] = $f; } @@ -174,7 +174,7 @@ public function readFills() foreach ($this->xlsx->styles->fills->fill as $v) { if (isset($v->patternFill)) { $this->fills[] = [ - 'pattern' => isset($v->patternFill['patternType']) ? (string) $v->patternFill['patternType'] : 'none', + 'pattern' => isset($v->patternFill['patternType']) ? htmlspecialchars((string) $v->patternFill['patternType'], ENT_QUOTES) : 'none', 'fgcolor' => $this->getColorValue($v->patternFill->fgColor), 'bgcolor' => $this->getColorValue($v->patternFill->bgColor) ]; @@ -185,35 +185,37 @@ public function readFills() public function readBorders() { $this->borders = []; + $styles = ['none', 'thin', 'medium', 'dashed', 'dotted', 'thick', 'double', 'hair', 'mediumDashed', 'dashDot', + 'mediumDashDot', 'dashDotDot', 'mediumDashDotDot', 'slantDashDot']; if (isset($this->xlsx->styles->borders->border)) { foreach ($this->xlsx->styles->borders->border as $v) { $this->borders[] = [ 'left' => [ - 'style' => (string) $v->left['style'], + 'style' => in_array((string) $v->left['style'], $styles) ? (string) $v->left['style'] : 'none', 'color' => $this->getColorValue($v->left->color) ], 'right' => [ - 'style' => (string) $v->right['style'], + 'style' => in_array((string) $v->right['style'], $styles) ? (string) $v->right['style'] : 'none', 'color' => $this->getColorValue($v->right->color) ], 'top' => [ - 'style' => (string) $v->top['style'], + 'style' => in_array((string) $v->top['style'], $styles) ? (string) $v->top['style'] : 'none', 'color' => $this->getColorValue($v->top->color) ], 'bottom' => [ - 'style' => (string) $v->bottom['style'], + 'style' => in_array((string) $v->bottom['style'], $styles) ? (string) $v->bottom['style'] : 'none', 'color' => $this->getColorValue($v->bottom->color) ], 'diagonal' => [ - 'style' => (string) $v->diagonal['style'], + 'style' => in_array((string) $v->diagonal['style'], $styles) ? (string) $v->diagonal['style'] : 'none', 'color' => $this->getColorValue($v->diagonal->color) ], 'horizontal' => [ - 'style' => (string) $v->horizontal['style'], + 'style' => in_array((string) $v->horizontal['style'], $styles) ? (string) $v->horizontal['style'] : 'none', 'color' => $this->getColorValue($v->horizontal->color) ], 'vertical' => [ - 'style' => (string) $v->vertical['style'], + 'style' => in_array((string) $v->vertical['style'], $styles) ? (string) $v->vertical['style'] : 'none', 'color' => $this->getColorValue($v->vertical->color) ], 'diagonalUp' => (bool) $v['diagonalUp'], @@ -616,7 +618,7 @@ public function getColorValue(SimpleXMLElement $a = null, $default = '') } $c = $default; // auto if ($a['rgb'] !== null) { - $c = substr((string) $a['rgb'], 2); // FFCCBBAA -> CCBBAA + $c = substr((string) $a['rgb'], 2, 6); // FFCCBBAA -> CCBBAA } elseif ($a['indexed'] !== null && isset(static::$IC[ (int) $a['indexed'] ])) { $c = static::$IC[ (int) $a['indexed'] ]; } elseif ($a['theme'] !== null && isset($this->themeColors[ (int) $a['theme'] ])) {
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4News mentions
0No linked articles in our index yet.