Wysoka

Angular SSR: XSS via Unescaped Processing Instruction (<?...?>) Nodes in Fallback Raw-Content Elements

  • Ujawniono: 28.09.2026
  • Aktualizacja: 11.10.2026 10:22

Summary

An XSS vulnerability exists in @angular/platform-server during server-side rendering (SSR) HTML serialization of ProcessingInstruction DOM nodes (<?target data?>, nodeType === 7) when nested inside fallback raw-content elements (<noscript>, <iframe>, <noembed>, <noframes>). While processing instruction data escaped > to &gt;, it did not check for or escape matching closing tags of ancestor fallback elements (e.g., </noscript>). When rendered in a browser with scripting enabled, an unescaped closing tag sequence in a processing instruction prematurely closes the fallback raw-content tag and causes subsequent sibling elements to execute as live HTML.

Technical Description

In HTML5 parsing, fallback raw-content elements (<noscript>, <iframe>, <noembed>, <noframes>) place the browser's HTML tokenizer into RAWTEXT mode. In RAWTEXT mode, processing instruction tokens (<?...?>) are treated as literal raw text rather than bogus comments, and the parser ignores > or ?>. The only token sequence that terminates the container is an end tag matching the container tag name (</noscript, </iframe, etc.).

During server-side HTML serialization, processing instruction nodes previously only replaced > with &gt; (preventing bogus comment breakouts in normal HTML data states) but left < untouched. Crucially, processing instruction serialization never inspected ancestor fallback raw-content tags. As a result, if a ProcessingInstruction node inside <noscript> contained </noscript in its data payload, it was emitted unescaped as <?x </noscript ?>.

Impact & Reachability

  • Reachability: Processing instruction nodes cannot be authored directly through standard Angular template syntax (which parses <?...> into comment nodes in DOM position). Reaching this vulnerability requires application or library code calling inject(DOCUMENT).createProcessingInstruction(target, data) or Renderer2 DOM insertion methods with untrusted user input passed to data inside a fallback raw-content container.
  • Impact: In applications that programmatically construct processing instruction nodes inside fallback elements during server-side rendering, an attacker controlling the processing instruction data can break out of the container and execute arbitrary JavaScript in victims' browsers.

Proof of Concept (Minimal Reproduction)

ts
import { Component, ElementRef, Renderer2, inject, DOCUMENT, AfterViewInit } from '@angular/core';

@Component({
  selector: 'app-root',
  standalone: true,
  template: `<noscript id="host"></noscript>`
})
export class AppComponent implements AfterViewInit {
  private r = inject(Renderer2);
  private el = inject(ElementRef);
  private doc = inject(DOCUMENT);

  ngAfterViewInit() {
    const host = this.el.nativeElement.querySelector('#host');
    
    // Attacker-controlled input passed as Processing Instruction data
    const pi = this.doc.createProcessingInstruction('x', '</noscript ');
    this.r.appendChild(host, pi);
    
    // Sibling markup that should remain inert inside <noscript>
    const img = this.r.createElement('img');
    this.r.setAttribute(img, 'src', 'x');
    this.r.setAttribute(img, 'onerror', 'alert("SSR_PI_XSS")');
    this.r.appendChild(host, img);
  }
}

Vulnerable SSR Output:

html
<noscript><?x </noscript ?><img src="x" onerror="alert('SSR_PI_XSS')"></noscript>

Workarounds

  • Avoid passing untrusted user input into document.createProcessingInstruction(target, data) when the node is inserted into <noscript>, <iframe>, <noembed>, or <noframes> during server-side rendering.
  • Manually sanitize or replace < with &lt; in any untrusted data passed to processing instruction nodes on the server.

Czego dotyczy

Kliknij technologię, aby zobaczyć wszystkie dotyczące jej podatności.

PlatformaPaczkaPodatne wersjePoprawka w wersji
Paczka npm @angular/platform-server >= 22.0.0, < 22.1.4, >= 21.0.0, < 21.2.22, >= 20.0.0, < 20.3.30, <= 19.2.25 22.1.4, 21.2.22, 20.3.30

Odnośniki

Ocena CVSS -
Wektor CVSS
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N
Słabość (CWE)
CWE-116, CWE-79
Platforma
npm
Paczka
@angular/platform-server
Ujawniono
28.09.2026
Aktualizacja
11.10.2026 10:22

Źródła i licencje

OSV / GitHub Advisory Database - GHSA-j3r3-mxqp-r2p4 - CC BY 4.0

Historia podatności: @angular/platform-server

Wszystkie opisane podatności tej paczki (Paczka npm), od najnowszej. Widać, czy to jednorazowa wpadka, czy paczka, której trzeba pilnować.

Wszystkie (12) w archiwum
Wszystkich wpisów
12
Pierwsza → ostatnia
09.2025 10.2026
Bez poprawki
0
Wykorzystywana w atakach
0

Rozkład istotności

  • Wysoka 11
  • Średnia 1

Ujawnienia w latach

  1. 2025: 1
  2. 2026: 11
Istotność:
  1. Wysoka CVE-2026-101895 >= 22.0.0, < 22.1.6, >= 21.0.0, < 21.2.23, >= 20.0.0, < 20.3.31, <= 19.2.25 22.1.6, 21.2.23, 20.3.31
  2. Angular SSR: XSS via Unescaped Processing Instruction (<?...?>) Nodes in Fallback Raw-Content Elements ten wpis
    Wysoka CVE-2026-88058 >= 22.0.0, < 22.1.4, >= 21.0.0, < 21.2.22, >= 20.0.0, < 20.3.30, <= 19.2.25 22.1.4, 21.2.22, 20.3.30
  3. Wysoka CVE-2026-88060 >= 22.0.0, < 22.1.4, >= 21.0.0, < 21.2.22, >= 20.0.0, < 20.3.30, <= 19.2.25 22.1.4, 21.2.22, 20.3.30
  4. Wysoka CVE-2026-88056 >= 22.0.0, < 22.1.4, >= 21.0.0, < 21.2.22, >= 20.0.0, < 20.3.30, <= 19.2.25 22.1.4, 21.2.22, 20.3.30
  5. Wysoka CVE-2026-69149 >= 22.0.0-next.0, < 22.0.7, >= 21.0.0-next.0, < 21.2.19, >= 20.0.0-next.0, < 20.3.27, <= 19.2.25 22.0.7, 21.2.19, 20.3.27
  6. Wysoka CVE-2026-50556 >= 22.0.0-next.0, < 22.0.0-rc.2, >= 21.0.0-next.0, < 21.2.16, >= 20.0.0-next.0, < 20.3.24, >= 19.0.0-next.0, < 19.2.25, <= 18.2.14 22.0.0-rc.2, 21.2.16, 20.3.24, 19.2.25
  7. Wysoka · 6.1 CVE-2026-50555 >= 22.0.0-next.0, < 22.0.0-rc.2, >= 21.0.0-next.0, < 21.2.16, >= 20.0.0-next.0, < 20.3.24, >= 19.0.0-next.0, < 19.2.25, <= 18.2.14 22.0.0-rc.2, 21.2.16, 20.3.24, 19.2.25
  8. Wysoka · 8.2 CVE-2026-50168 >= 22.0.0-next.0, < 22.0.0-rc.2, >= 20.0.0-next.0, < 20.3.22, >= 19.0.0-next.0, < 19.2.23, <= 18.2.14, >= 21.0.0-next.0, < 21.2.15 22.0.0-rc.2, 20.3.22, 19.2.23, 21.2.15
  9. Wysoka · 6.1 CVE-2026-46417 >= 22.0.0-next.0, < 22.0.0-next.12, >= 21.0.0-next.0, < 21.2.13, >= 20.0.0-next.0, < 20.3.21, >= 19.0.0-next.0, < 19.2.22, <= 18.2.14 22.0.0-next.12, 21.2.13, 20.3.21, 19.2.22
  10. Wysoka CVE-2026-41423 >= 22.0.0-next.0, < 22.0.0-next.8, >= 21.0.0-next.0, < 21.2.9, >= 20.0.0-next.0, < 20.3.19, >= 19.0.0-next.0, < 19.2.21, <= 18.2.14 22.0.0-next.8, 21.2.9, 20.3.19, 19.2.21
  11. Wysoka CVE-2025-59052 >= 16.0.0-next.0, < 18.2.14, >= 20.0.0-next.0, < 20.3.0, >= 19.0.0-next.0, < 19.2.15, >= 21.0.0-next.0, < 21.0.0-next.3 18.2.14, 20.3.0, 19.2.15, 21.0.0-next.3

Dowiedz się, które podatności dotyczą Twojej aplikacji

Po podłączeniu integracji DockRay i włączeniu raportowania oprogramowania DockRay porównuje zgłoszone wersje komponentów ze znanymi podatnościami i powiadamia o potwierdzonych dopasowaniach. Zakres zależy od obsługiwanej technologii i dostępnych biuletynów.

Podłącz swoją aplikację
Newsletter DockRay

Bezpieczeństwo aplikacji w Twojej skrzynce

Najważniejsze podatności, konkretne zalecenia i praktyczne wskazówki dla Twoich aplikacji. Wybierz technologie i śledź to, co ma znaczenie dla Twojego projektu.

  • Codzienne zestawienie nowych podatności, także krytycznych.
  • Powiadomienia o ważnych aktualizacjach.
  • Praktyczne porady o bezpieczeństwie i monitoringu aplikacji.

Pozostaw puste, aby otrzymywać informacje o wszystkich technologiach.

Zapis jest bezpłatny. Wypiszesz się jednym kliknięciem w wiadomości.