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: 1. Per DOM specifications, the children of a <template> element reside in a separate DocumentFragment (template.content), whose own parentNode is null. 2. The serializer's ancestor traversal previously only inspected element nodes. When traversing upward from a node inside template.content, traversal terminated immediately at the DocumentFragment boundary. 3. 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 (CUSTOMELEMENTSSCHEMA or NOERRORSSCHEMA). 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 Renderer2 bypass template compiler schema checks entirely and are unconditionally affected.
Proof of Concept (Minimal Reproduction) ts import { Component } from '@angular/core';
@Component({ selector: 'app-root', standalone: true, template: <noscript> <template> <xmp>{{ payload }}</xmp> </template> </noscript> }) export class AppComponent { // Attacker-controlled input bound via standard text interpolation payload = '</noscript><img src=x onerror=alert("SSRTEMPLATEXSS")>'; } Vulnerable SSR Output: html <noscript><template><xmp></noscript><img src=x onerror=alert("SSRTEMPLATEXSS")></xmp></template></noscript>
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.
Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages. Versions prior to 21.2.0, 21.1.16, 20.3.17, and 19.2.19 have a cross-Site scripting vulnerability in the Angular internationalization (i18n) pipeline. In ICU messages (International Components for Unicode), HTML from translated content was not properly sanitized and could execute arbitrary JavaScript. Angular i18n typically involves three steps, extracting all messages from an application in the source language, sending the messages to be translated, and then merging their translations back into the final source code. Translations are frequently handled by contracts with specific partner companies, and involve sending the source messages to a separate contractor before receiving final translations for display to the end user. If the returned translations have malicious content, it could be rendered into the application and execute arbitrary JavaScript. When successfully exploited, this vulnerability allows for execution of attacker controlled JavaScript in the application origin. Depending on the nature of the application being exploited this could lead to credential exfiltration and/or page vandalism. Several preconditions apply to the attack. The attacker must compromise the translation file (xliff, xtb, etc.). Unlike most XSS vulnerabilities, this issue is not exploitable by arbitrary users. An attacker must first compromise an application's translation file before they can escalate privileges into the Angular application client. The victim application must use Angular i18n, use one or more ICU messages, render an ICU message, and not defend against XSS via a safe content security policy. Versions 21.2.0, 21.1.6, 20.3.17, and 19.2.19 patch the issue. Until the patch is applied, developers should consider reviewing and verifying translated content received from untrusted third parties before incorporating it in an Angular application, enabling strict CSP controls to block unauthorized JavaScript from executing on the page, and enabling Trusted Types to enforce proper HTML sanitization.
A vulnerability was found in Angular up to 11.0.4/11.1.0-next.2. It has been classified as problematic. Affected is the handling of comments. The manipulation leads to cross site scripting. It is possible to launch the attack remotely but it might require an authentication first. Upgrading to version 10.2.5, 11.0.5 or 11.1.0-next.3 is advised to to address this issue.