CVE-2026-46637 Overview
CVE-2026-46637 is a Cross-Site Scripting (XSS) vulnerability affecting Symfony Twig, a widely used template language for PHP. The flaw exists in the twig/markdown-extra and twig/cssinliner-extra packages prior to version 3.26.0. Several filters register with is_safe => [all], causing Twig to treat plain text or HTML output as safe across HTML, JavaScript, CSS, URL, and other rendering contexts. As a result, attacker-controlled content passing through these filters bypasses Twig's automatic contextual escaping. The issue was resolved in Twig 3.26.0 by tightening the is_safe annotation and pre-escaping HTML input on affected filters.
Critical Impact
Untrusted content processed through markdown_to_html, html_to_markdown, inline_css, or inky_to_html filters can execute arbitrary script in a victim's browser when rendered in non-HTML contexts.
Affected Products
- Symfony Twig versions prior to 3.26.0
- twig/markdown-extra package (filters markdown_to_html, html_to_markdown)
- twig/cssinliner-extra and twig/inky-extra packages (filters inline_css, inky_to_html)
Discovery Timeline
- 2026-07-14 - CVE-2026-46637 published to NVD
- 2026-07-16 - Last updated in NVD database
Technical Details for CVE-2026-46637
Vulnerability Analysis
Twig applies automatic output escaping based on the rendering context. Filters that emit already-escaped or trusted content can register with an is_safe annotation to bypass this escaping. The affected filters in twig/markdown-extra and twig/cssinliner-extra declared themselves safe for all contexts, including JavaScript, CSS, and URL. This annotation is incorrect because the filters emit HTML that is only safe when rendered inside an HTML context. When a developer places filter output inside a <script> block, a CSS declaration, or a URL attribute, Twig skips escaping and the raw HTML is inserted directly. Attackers who control markdown or HTML input can inject script payloads that execute in the victim's browser. This maps to [CWE-79] Cross-Site Scripting and [CWE-116] Improper Encoding or Escaping of Output.
Root Cause
The root cause is an overly broad is_safe annotation on filters that only produce HTML-safe output. Declaring is_safe => ['all'] disables Twig's contextual escaping in every rendering context, including JavaScript and CSS where HTML escaping is insufficient.
Attack Vector
Exploitation requires an authenticated user to submit content that flows through one of the vulnerable filters and is subsequently rendered in a non-HTML context within a Twig template. User interaction is required to trigger the payload in a victim's browser.
// Patch 1: extra/cssinliner-extra/CssInlinerExtension.php
// Restrict is_safe from 'all' to 'html' only
public function getFilters(): array
{
return [
- new TwigFilter('inline_css', [self::class, 'inlineCss'], ['is_safe' => ['all']]),
+ new TwigFilter('inline_css', [self::class, 'inlineCss'], ['is_safe' => ['html']]),
];
}
Source: twigphp/Twig commit 84982072
// Patch 2: extra/markdown-extra/MarkdownExtension.php
public function getFilters(): array
{
return [
- new TwigFilter('markdown_to_html', ['Twig\\Extra\\Markdown\\MarkdownRuntime', 'convert'], ['is_safe' => ['all']]),
- new TwigFilter('html_to_markdown', [self::class, 'htmlToMarkdown'], ['is_safe' => ['all']]),
+ new TwigFilter('markdown_to_html', ['Twig\\Extra\\Markdown\\MarkdownRuntime', 'convert'], ['is_safe' => ['html']]),
+ new TwigFilter('html_to_markdown', [self::class, 'htmlToMarkdown']),
];
}
Source: twigphp/Twig commit 84982072
// Patch 3: Pre-escape HTML input on inline_css and inky_to_html
public function getFilters(): array
{
return [
- new TwigFilter('inline_css', [self::class, 'inlineCss'], ['is_safe' => ['html']]),
+ new TwigFilter('inline_css', [self::class, 'inlineCss'], ['is_safe' => ['html'], 'pre_escape' => 'html']),
];
}
Source: twigphp/Twig commit e36489d3
Detection Methods for CVE-2026-46637
Indicators of Compromise
- Twig template code invoking markdown_to_html, html_to_markdown, inline_css, or inky_to_html filters where the output is placed inside <script>, <style>, or URL attribute contexts.
- Composer lock files pinning twig/markdown-extra or twig/cssinliner-extra to versions below 3.26.0.
- Web server logs showing unusual POST payloads containing markdown or HTML with embedded <script> or javascript: sequences targeted at pages that render user content.
Detection Strategies
- Perform a static scan of Twig templates for the affected filter names combined with output placement in non-HTML contexts.
- Audit composer.lock across projects to identify installations of twig/markdown-extra or twig/cssinliner-extra prior to 3.26.0.
- Deploy Content Security Policy (CSP) violation reporting to surface unexpected inline script execution originating from rendered templates.
Monitoring Recommendations
- Monitor web application logs for reflected user input rendered through markdown or CSS inliner pipelines.
- Enable CSP report-only mode on pages that render user-submitted markdown, and alert on script-src violations.
- Track dependency updates in CI/CD to flag any downgrade or pinning of Twig extras packages below the patched version.
How to Mitigate CVE-2026-46637
Immediate Actions Required
- Upgrade twig/markdown-extra, twig/cssinliner-extra, and twig/inky-extra to version 3.26.0 or later.
- Review Twig templates for use of the affected filters and confirm output is only rendered inside HTML contexts.
- Apply strict input validation and sanitization on any user-supplied markdown or HTML processed by these filters.
Patch Information
The vulnerability is fixed in Twig 3.26.0. The fix consists of two commits: commit 84982072 restricts the is_safe annotation from all to html on the affected filters, and commit e36489d3 adds pre_escape => 'html' on the inline_css and inky_to_html filters. Full details are available in GitHub Security Advisory GHSA-jv8m-2544-3pg3 and the v3.26.0 release notes.
Workarounds
- If patching is not immediately possible, wrap filter output with explicit context-specific escaping such as {{ value|markdown_to_html|escape('js') }} when rendered inside JavaScript contexts.
- Restrict use of the affected filters to templates that render output only inside HTML body contexts.
- Implement a strict Content Security Policy that disallows inline scripts to reduce the impact of successful injection.
# Upgrade the affected Twig extras packages to the patched version
composer require twig/markdown-extra:^3.26.0 twig/cssinliner-extra:^3.26.0 twig/inky-extra:^3.26.0
# Verify installed versions
composer show twig/markdown-extra twig/cssinliner-extra twig/inky-extra
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

