CVE-2026-47730 Overview
CVE-2026-47730 is a Cross-Site Scripting (XSS) vulnerability in Twig, a widely used template language for PHP. The flaw resides in Twig\Profiler\Dumper\HtmlDumper, which writes the output of Profile::getTemplate() and Profile::getName() directly into HTML without escaping. Attacker-controlled template or profile names can inject arbitrary HTML that executes when a browser renders the profiler dump. The issue affects Twig versions 3.0.0 through 3.25.x and is fixed in version 3.26.0. The vulnerability is classified under [CWE-79] (Improper Neutralization of Input During Web Page Generation).
Critical Impact
Attackers who can influence template or profile names can inject arbitrary HTML or JavaScript into rendered profiler dumps, enabling session theft, credential harvesting, or malicious redirects in developer and staging environments.
Affected Products
- Symfony Twig versions 3.0.0 through 3.25.x
- PHP applications using Twig\Profiler\Dumper\HtmlDumper
- Development and profiling environments exposing Twig profiler output in browsers
Discovery Timeline
- 2026-07-14 - CVE-2026-47730 published to NVD
- 2026-07-16 - Last updated in NVD database
Technical Details for CVE-2026-47730
Vulnerability Analysis
The vulnerability exists in the HtmlDumper class within Twig's profiler component. This class formats profiling data as HTML for developer inspection. Two methods, formatTemplate() and formatNonTemplate(), interpolate the return values of $profile->getTemplate() and $profile->getName() into HTML strings using sprintf() without applying HTML escaping.
When template or profile names originate from untrusted input, such as user-supplied file paths, dynamic includes, or attacker-influenced identifiers, the raw values are inserted directly into the generated markup. A browser rendering the profiler dump then interprets any embedded HTML or <script> tags as executable content. The impact is bounded by the environments where profiler output is exposed, typically development, staging, or debugging pages, but reflected XSS in those contexts still enables session hijacking against developers or administrators.
Root Cause
The root cause is missing output encoding in the profiler dumper. Twig's core rendering pipeline auto-escapes output, but the profiler dumper wrote profile metadata to HTML using string formatting rather than the htmlspecialchars() function. Any string containing <, >, ", or ' characters passes through unchanged.
Attack Vector
Exploitation requires that an attacker control a value ultimately returned by Profile::getTemplate() or Profile::getName(). A victim then views the rendered profiler dump in a browser. User interaction is required, and the attacker needs at least low privileges to influence template naming. The following patch shows the fix applied in version 3.26.0.
protected function formatTemplate(Profile $profile, $prefix): string
{
- return \sprintf('%s└ <span style="background-color: %s">%s</span>', $prefix, self::$colors['template'], $profile->getTemplate());
+ return \sprintf('%s└ <span style="background-color: %s">%s</span>', $prefix, self::$colors['template'], self::escape($profile->getTemplate()));
}
protected function formatNonTemplate(Profile $profile, $prefix): string
{
- return \sprintf('%s└ %s::%s(<span style="background-color: %s">%s</span>)', $prefix, $profile->getTemplate(), $profile->getType(), self::$colors[$profile->getType()] ?? 'auto', $profile->getName());
+ return \sprintf('%s└ %s::%s(<span style="background-color: %s">%s</span>)', $prefix, self::escape($profile->getTemplate()), $profile->getType(), self::$colors[$profile->getType()] ?? 'auto', self::escape($profile->getName()));
}
+ private static function escape(string $value): string
+ {
+ return htmlspecialchars($value, \ENT_QUOTES | \ENT_SUBSTITUTE, 'UTF-8');
+ }
Source: Twig commit a5f6e879
Detection Methods for CVE-2026-47730
Indicators of Compromise
- HTML profiler dump pages containing unexpected <script>, <img>, <iframe>, or event handler attributes such as onerror= and onload= within template or profile name fields
- Outbound browser requests from developer or staging hosts to unknown external domains triggered from profiler pages
- Unusual template names in application logs containing HTML metacharacters like <, >, or quote characters
Detection Strategies
- Scan application dependency manifests (composer.lock, composer.json) for twig/twig versions below 3.26.0
- Review web server access logs for requests to profiler endpoints originating from external or unauthenticated sources
- Inspect rendered profiler HTML output for unescaped angle brackets or scripting payloads in template and profile name positions
Monitoring Recommendations
- Enable Content Security Policy (CSP) reporting on any environment that may expose Twig profiler output and monitor script-src violations
- Monitor for the presence of Twig\Profiler\Dumper\HtmlDumper invocations in production code paths, which should not occur in production deployments
- Alert on modifications to Twig profiler configuration files or environment flags that enable profiling
How to Mitigate CVE-2026-47730
Immediate Actions Required
- Upgrade twig/twig to version 3.26.0 or later using composer update twig/twig
- Disable the Twig profiler in any production environment and restrict access to profiler dump pages
- Audit codebases for direct use of Twig\Profiler\Dumper\HtmlDumper and confirm template and profile names originate from trusted sources
Patch Information
The fix is available in Twig version 3.26.0. The patch introduces a private escape() helper that applies htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') to both Profile::getTemplate() and Profile::getName() before interpolation. Refer to the GitHub Security Advisory GHSA-2g2g-8p8h-fgwm and the Twig v3.26.0 release notes for full details.
Workarounds
- Replace HtmlDumper with Twig\Profiler\Dumper\TextDumper or BlackfireDumper, which do not emit HTML
- Wrap profiler output with an application-level HTML sanitizer before returning it to the browser
- Enforce a strict Content Security Policy that blocks inline script execution on any page that renders profiler output
# Upgrade Twig to the patched release
composer require twig/twig:^3.26.0
# Verify installed version
composer show twig/twig | grep versions
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

