Описание
Angular: SSR XSS via Unescaped <template> Content Across DocumentFragment Boundaries in Fallback Raw-Content Elements
Summary
An XSS vulnerability exists in @angular/platform-server during server-side rendering (SSR) HTML serialization when traversing ancestor tags across <template> element boundaries. When an application renders untrusted user input within raw-text tags (<xmp>, <style>, <script>), comments, or text nodes inside a <template> that is nested within a fallback raw-content element (<noscript>, <iframe>, <noembed>, <noframes>), matching closing tags (e.g., </noscript>) are not escaped during HTML serialization. When rendered in a browser, this unescaped closing tag prematurely terminates the fallback container and executes trailing markup as active DOM elements.
Technical Description
In HTML5 parsing, fallback raw-content elements (<noscript>, <iframe>, <noembed>, <noframes>) place the browser's tokenizer into RAWTEXT mode. In this mode, inner content is parsed as literal text until an end tag matching the container tag name (e.g., </noscript>) is encountered.
To prevent XSS breakout vectors during SSR serialization, the DOM serializer inspects a node's ancestors to escape any matching fallback closing tags (</tag -> </tag). However:
- Per DOM specifications, the children of a
<template>element reside in a separateDocumentFragment(template.content), whose ownparentNodeisnull. - The serializer's ancestor traversal previously only inspected element nodes. When traversing upward from a node inside
template.content, traversal terminated immediately at theDocumentFragmentboundary. - Because traversal stopped before reaching the outer document tree, enclosing fallback raw-content ancestors (such as
<noscript>or<iframe>) were not discovered. As a result, closing sequences like</noscript>within<template>content were emitted unescaped.
Impact & Reachability
- Framework Guarantee Bypass: Angular guarantees that standard text interpolation (
{{ userInput }}bound as element text content) is safe by default without manual sanitization. This vulnerability bypasses that guarantee during SSR HTML serialization when untrusted input is interpolated inside template content within fallback containers. - Template Authoring: Writing literal
<xmp>or<style>directly inside a component's<template>markup requires relaxed template schema checks (CUSTOM_ELEMENTS_SCHEMAorNO_ERRORS_SCHEMA). However, standard HTML comments and text nodes inside<template>within<noscript>are reachable without relaxed schemas. - Imperative DOM Construction: Components or directives that construct DOM structures imperatively via
Renderer2bypass template compiler schema checks entirely and are unconditionally affected.
Proof of Concept (Minimal Reproduction)
Vulnerable SSR Output:
Workarounds
- Avoid rendering untrusted user input inside
<template>elements nested within<noscript>,<iframe>,<noembed>, or<noframes>in server-rendered templates. - Avoid programmatic DOM assembly of
<template>elements inside fallback containers when handling untrusted data.
Ссылки
- https://github.com/angular/angular/security/advisories/GHSA-v3p8-whq6-r5jg
- https://github.com/angular/angular/commit/73d8bbd27cb46495426d4132975a1355b47ad915
- https://github.com/angular/angular/commit/89b20568dfaee1ec8e0b3bcf1872acdddd2f4fef
- https://github.com/angular/angular/commit/ba3bc47b20b3d12f5eb141ec9c651373ae4d15e8
- https://github.com/angular/domino/commit/04f987dc08ff3736b427f50941adf1722458528f
- https://github.com/angular/angular/releases/tag/v20.3.30
- https://github.com/angular/angular/releases/tag/v21.2.22
- https://github.com/angular/angular/releases/tag/v22.1.4
Пакеты
@angular/platform-server
>= 22.0.0, < 22.1.4
22.1.4
@angular/platform-server
>= 21.0.0, < 21.2.22
21.2.22
@angular/platform-server
>= 20.0.0, < 20.3.30
20.3.30
@angular/platform-server
<= 19.2.25
Отсутствует
Связанные уязвимости
Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages. Prior to 20.3.30, 21.2.22, and 22.1.4, Angular server-side rendering (SSR) in @angular/platform-server serializes untrusted input inside template content nested in fallback raw-content elements such as noscript, iframe, noembed, and noframes. The Domino serializer's fallbackRawContentTags traversal stopped at the DocumentFragment used by template.content, so matching closing tags in xmp, style, script, comments, or text nodes were not escaped. Standard interpolation with comments or text nodes is reachable without relaxed schemas; literal xmp or style requires CUSTOM_ELEMENTS_SCHEMA or NO_ERRORS_SCHEMA, while Renderer2 imperative DOM construction is unconditionally affected. When HTML5 RAWTEXT browser parsing encounters the unescaped closing tag, it exits the fallback container and interprets trailing markup as active DOM elements, enabling arbitrary Ja...
Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages. Prior to 20.3.30, 21.2.22, and 22.1.4, Angular server-side rendering (SSR) in @angular/platform-server serializes untrusted input inside template content nested in fallback raw-content elements such as noscript, iframe, noembed, and noframes. The Domino serializer's fallbackRawContentTags traversal stopped at the DocumentFragment used by template.content, so matching closing tags in xmp, style, script, comments, or text nodes were not escaped. Standard interpolation with comments or text nodes is reachable without relaxed schemas; literal xmp or style requires CUSTOM_ELEMENTS_SCHEMA or NO_ERRORS_SCHEMA, while Renderer2 imperative DOM construction is unconditionally affected. When HTML5 RAWTEXT browser parsing encounters the unescaped closing tag, it exits the fallback container and interprets trailing markup as active DOM elements, enabling arbitrary JavaS
Angular is a development platform for building mobile and desktop web ...