Cross-Site Scripting in TYPO3 Fluid Engine
Description
TYPO3 Fluid Engine (package typo3fluid/fluid) before versions 2.0.5, 2.1.4, 2.2.1, 2.3.5, 2.4.1, 2.5.5 or 2.6.1 is vulnerable to cross-site scripting when making use of the ternary conditional operator in templates like {showFullName ? fullName : defaultValue}. Updated versions of this package are bundled in following TYPO3 (typo3/cms-core) versions as well: TYPO3 v8.7.25 (using typo3fluid/fluid v2.5.4) and TYPO3 v9.5.6 (using typo3fluid/fluid v2.6.1).
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Cross-site scripting vulnerability in TYPO3 Fluid Engine when using ternary conditional operator in templates, allowing injection of arbitrary HTML/JavaScript.
Vulnerability
The TYPO3 Fluid Engine (package typo3fluid/fluid) is vulnerable to cross-site scripting (XSS) due to insufficient escaping of expression nodes when using the ternary conditional operator in templates, such as {showFullName ? fullName : defaultValue}. The root cause is that the EscapingNode was not applied to ExpressionNodeInterface instances, allowing unescaped output of user-controlled variables in ternary expressions [1][2].
Exploitation
An attacker can exploit this by injecting malicious HTML or JavaScript through template variables used within a ternary operator. No authentication is required if the template renders user-supplied data without proper sanitization. The attack surface includes any TYPO3 application that uses Fluid templates with ternary conditionals involving user input [1].
Impact
Successful exploitation allows an attacker to execute arbitrary HTML/JavaScript in the context of the victim's browser, potentially leading to session hijacking, defacement, or data theft. The vulnerability affects all versions of typo3fluid/fluid before 2.0.5, 2.1.4, 2.2.1, 2.3.5, 2.4.1, 2.5.5, or 2.6.1, and corresponding TYPO3 CMS versions [1].
Mitigation
The fix is included in the patched versions listed above. TYPO3 CMS v8.7.25 (bundles Fluid v2.5.4) and v9.5.6 (bundles Fluid v2.6.1) also contain the fix. Users should upgrade to the latest versions immediately [1][2].
AI Insight generated on May 21, 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 |
|---|---|---|
typo3fluid/fluidPackagist | >= 2.0.0, < 2.0.5 | 2.0.5 |
typo3fluid/fluidPackagist | >= 2.1.0, < 2.1.4 | 2.1.4 |
typo3fluid/fluidPackagist | >= 2.2.0, < 2.2.1 | 2.2.1 |
typo3fluid/fluidPackagist | >= 2.3.0, < 2.3.5 | 2.3.5 |
typo3fluid/fluidPackagist | >= 2.4.0, < 2.4.1 | 2.4.1 |
typo3fluid/fluidPackagist | >= 2.5.0, < 2.5.5 | 2.5.5 |
typo3fluid/fluidPackagist | >= 2.6.0, < 2.6.1 | 2.6.1 |
typo3/cms-corePackagist | >= 8.0.0, < 8.7.25 | 8.7.25 |
typo3/cms-corePackagist | >= 9.0.0, < 9.5.6 | 9.5.6 |
typo3/cmsPackagist | >= 8.0.0, < 8.7.25 | 8.7.25 |
typo3/cmsPackagist | >= 9.0.0, < 9.5.6 | 9.5.6 |
Affected products
5- osv-coords4 versions
>= 8.7.25, <= 8.7.25+ 3 more
- (no CPE)range: >= 8.7.25, <= 8.7.25
- (no CPE)range: >= 8.0.0, < 8.7.25
- (no CPE)range: >= 8.0.0, < 8.7.25
- (no CPE)range: >= 2.0.0, < 2.0.5
- TYPO3/Fluidv5Range: >= 2.0.0, < 2.0.5
Patches
19ef6a8ffff2e[BUGFIX] Ensure escaping of escapable ExpressionNode
5 files changed · +13 −3
examples/Resources/Private/Singles/Variables.html+3 −0 modified@@ -29,6 +29,7 @@ <!-- Passing arguments to sections/partials --> <f:render section="Secondary" arguments="{ + ternaryCheck: 1, myVariable: 'Nice string', array: { baz: 42, @@ -43,6 +44,8 @@ </f:section> <f:section name="Secondary"> +Escaped ternary expression: {ternaryCheck ? array.foobar : array.foobar} +Escaped cast expression: {array.foobar as string} Received $array.foobar with value {array.foobar -> f:format.raw()} (same using "value" argument: {f:format.raw(value: array.foobar)}) Received $array.printf with formatted string {array.printf -> f:format.printf(arguments: {0: 'formatted'})} Received $array.baz with value {array.baz}
src/Core/Parser/Interceptor/Escape.php+4 −2 modified@@ -9,6 +9,7 @@ use TYPO3Fluid\Fluid\Core\Parser\InterceptorInterface; use TYPO3Fluid\Fluid\Core\Parser\ParsingState; use TYPO3Fluid\Fluid\Core\Parser\SyntaxTree\EscapingNode; +use TYPO3Fluid\Fluid\Core\Parser\SyntaxTree\Expression\ExpressionNodeInterface; use TYPO3Fluid\Fluid\Core\Parser\SyntaxTree\NodeInterface; use TYPO3Fluid\Fluid\Core\Parser\SyntaxTree\ObjectAccessorNode; use TYPO3Fluid\Fluid\Core\Parser\SyntaxTree\ViewHelperNode; @@ -62,7 +63,7 @@ public function process(NodeInterface $node, $interceptorPosition, ParsingState if ($this->childrenEscapingEnabled && $node->getUninitializedViewHelper()->isOutputEscapingEnabled()) { $node = new EscapingNode($node); } - } elseif ($this->childrenEscapingEnabled && $node instanceof ObjectAccessorNode) { + } elseif ($this->childrenEscapingEnabled && ($node instanceof ObjectAccessorNode || $node instanceof ExpressionNodeInterface)) { $node = new EscapingNode($node); } return $node; @@ -78,7 +79,8 @@ public function getInterceptionPoints() return [ InterceptorInterface::INTERCEPT_OPENING_VIEWHELPER, InterceptorInterface::INTERCEPT_CLOSING_VIEWHELPER, - InterceptorInterface::INTERCEPT_OBJECTACCESSOR + InterceptorInterface::INTERCEPT_OBJECTACCESSOR, + InterceptorInterface::INTERCEPT_EXPRESSION, ]; } }
src/Core/Parser/InterceptorInterface.php+1 −0 modified@@ -19,6 +19,7 @@ interface InterceptorInterface const INTERCEPT_CLOSING_VIEWHELPER = 2; const INTERCEPT_TEXT = 3; const INTERCEPT_OBJECTACCESSOR = 4; + const INTERCEPT_EXPRESSION = 5; /** * The interceptor can process the given node at will and must return a node
src/Core/Parser/TemplateParser.php+2 −0 modified@@ -625,6 +625,8 @@ protected function textAndShorthandSyntaxHandler(ParsingState $state, $text, $co if ($expressionStartPosition > 0) { $state->getNodeFromStack()->addChildNode(new TextNode(substr($section, 0, $expressionStartPosition))); } + + $this->callInterceptor($expressionNode, InterceptorInterface::INTERCEPT_EXPRESSION, $state); $state->getNodeFromStack()->addChildNode($expressionNode); $expressionEndPosition = $expressionStartPosition + strlen($matchedVariableSet[0]);
tests/Functional/ExamplesTest.php+3 −1 modified@@ -218,6 +218,8 @@ public function getExampleScriptTestValues() 'Output of variable whose name is stored in a variable: string foo', 'Direct access of numeric prefixed variable: Numeric prefixed variable', 'Aliased access of numeric prefixed variable: Numeric prefixed variable', + 'Escaped ternary expression: <b>Unescaped string</b>', + 'Escaped cast expression: <b>Unescaped string</b>', 'Received $array.foobar with value <b>Unescaped string</b> (same using "value" argument: <b>Unescaped string</b>)', 'Received $array.printf with formatted string Formatted string, value: formatted', 'Received $array.baz with value 42', @@ -260,7 +262,7 @@ public function getExampleScriptTestValues() 'ViewHelper error: Undeclared arguments passed to ViewHelper TYPO3Fluid\Fluid\ViewHelpers\IfViewHelper: notregistered. Valid arguments are: then, else, condition - Offending code: <f:if notregistered="1" />', 'Parser error: The ViewHelper "<f:invalid>" could not be resolved.', 'Based on your spelling, the system would load the class "TYPO3Fluid\Fluid\ViewHelpers\InvalidViewHelper", however this class does not exist. Offending code: <f:invalid />', - 'Invalid expression: Invalid target conversion type "invalidtype" specified in casting expression "{foobar as invalidtype}".', + 'Invalid expression: Invalid target conversion type "invalidtype" specified in casting expression "{foobar as invalidtype}".', ] ] ];
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- github.com/advisories/GHSA-7733-hjv6-4h47ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2020-15241ghsaADVISORY
- github.com/FriendsOfPHP/security-advisories/blob/master/typo3/cms-core/CVE-2020-15241.yamlghsaWEB
- github.com/FriendsOfPHP/security-advisories/blob/master/typo3/cms/CVE-2020-15241.yamlghsaWEB
- github.com/FriendsOfPHP/security-advisories/blob/master/typo3fluid/fluid/CVE-2020-15241.yamlghsaWEB
- github.com/TYPO3/Fluid/commit/9ef6a8ffff2e812025fc0701b4ce72eea6911a3dghsax_refsource_MISCWEB
- github.com/TYPO3/Fluid/security/advisories/GHSA-7733-hjv6-4h47ghsax_refsource_CONFIRMWEB
- typo3.org/security/advisory/typo3-core-sa-2019-013ghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.