The vulnerability is a cross-site scripting (XSS) issue in typo3/html-sanitizer that occurs when the ALLOW_INSECURE_RAW_TEXT option is used. The root cause is twofold, involving both parsing and serialization logic.
-
Parsing Failure: The sanitizer relied on the masterminds/html5-php library for HTML parsing. The tokenizer in that library failed to correctly identify closing tags for raw text elements (like <style>) if they contained whitespace (e.g., </style \t>). Browsers, however, would correctly interpret this as a closing tag. This discrepancy allowed an attacker to craft input where malicious HTML following the malformed closing tag would be incorrectly consumed by the parser as part of the raw text content, rather than being parsed as distinct tags.
-
Insecure Serialization: When the ALLOW_INSECURE_RAW_TEXT flag was enabled for a tag, the TYPO3\HtmlSanitizer\Serializer\Rules::text() method would take the content of the parsed text node and output it directly, without any HTML encoding. Due to the parsing failure, this "raw text" contained the malicious HTML payload, which was then written unescaped into the final output, leading to XSS.
-
Incomplete noscript Handling: A related issue existed in the TYPO3\HtmlSanitizer\Serializer\Rules::shallAllowInsecureRawText() method. It did not prevent raw text passthrough inside <noscript> elements. This could be exploited because browsers with JavaScript enabled treat <noscript> content as raw text, which could hide inner closing tags from the sanitizer and allow payloads to escape.
The patch addresses these issues by:
- Introducing a custom parser (
TYPO3\HtmlSanitizer\Parser\Html5) and tokenizer (TYPO3\HtmlSanitizer\Parser\Tokenizer) that correctly handle whitespace in closing tags, overriding the vulnerable behavior of the dependency. The key change is in the rawText() method.
- Adding a check in
TYPO3\HtmlSanitizer\Serializer\Rules::shallAllowInsecureRawText() to deny raw text behavior for any element within a <noscript> tag.
The identified vulnerable functions are the key components within typo3/html-sanitizer that were either directly responsible for the insecure serialization (Rules::text), had insufficient security checks (Rules::shallAllowInsecureRawText), or were responsible for using the vulnerable parsing component (Sanitizer::createParser).