XSS Vulnerability in Angular Server-Side Rendering via Processing Instructions
Angular platform-server is vulnerable to XSS when ProcessingInstruction nodes containing untrusted input are nested within fallback raw-content elements during server-side rendering.
CVE search metadata
CVE search record: CVE-2026-88058. EPSS: 0.88%. KEV: no. Product: platform-server (>= 22.0.0, < 22.1.4), platform-server (>= 21.0.0, < 21.2.22), platform-server (>= 20.0.0, < 20.3.30), platform-server (<= 19.2.25). Brief: XSS Vulnerability in Angular Server-Side Rendering via Processing Instructions. Brief link: https://feed.craftedsignal.io/briefs/2026-09-angular-ssr-xss/
Triage facts
- Applicability
- platform-server (>= 22.0.0, < 22.1.4), platform-server (>= 21.0.0, < 21.2.22) +2
- Severity
- High
- Action
- Elevated
- Sources
- 2 public sources
- Freshness
- PublishedSep 28, 22:15 UTC
- Vulnerabilities
- 1 CVE
Angular's @angular/platform-server package contains an XSS vulnerability (CVE-2026-88058) affecting server-side rendering (SSR) serialization of DOM ProcessingInstruction nodes. When these nodes are nested inside fallback raw-content elements like <noscript>, <iframe>, <noembed>, or <noframes>, the serializer fails to properly escape the closing tags of ancestor containers (e.g., </noscript>) within the processing instruction data.
In browsers, fallback raw-content elements cause the parser to enter RAWTEXT mode, where the parser looks for specific closing tag sequences to terminate the block. Because the Angular SSR serializer only escaped > and not <, an attacker providing a payload containing </noscript within a ProcessingInstruction can cause the browser to prematurely close the container and treat sibling elements as active HTML. This allows for arbitrary JavaScript execution in the context of the user's session. The vulnerability affects multiple versions across Angular 19 through 22.
Attack Chain
- Application or library code programmatically calls
inject(DOCUMENT).createProcessingInstruction(target, data)or usesRenderer2to insert nodes. - The application passes untrusted user input as the
dataparameter for theProcessingInstructionnode. - The node is inserted into a container that uses a fallback raw-content element (e.g.,
<noscript>). - The Angular server-side rendering engine serializes the DOM state to an HTML string.
- The serializer fails to escape the
<character in the processing instruction data, emitting<?x </noscript ?>. - The generated HTML string is sent to the client browser.
- The client browser parses the HTML in
RAWTEXTmode; the</noscriptsequence terminates the<noscript>block. - Sibling markup elements following the breakout sequence are parsed as live HTML, executing injected malicious JavaScript.
Impact
Successful exploitation allows for reflected or stored XSS depending on how the application handles input and rendering, leading to potential session hijacking, unauthorized actions on behalf of the user, or theft of sensitive data within the application. The reachability depends on the application's programmatic use of the ProcessingInstruction API with untrusted data, which is uncommon but possible in custom Angular library or component logic.
Recommendation
- Upgrade to patched versions of
@angular/platform-server(e.g., >= 22.1.4, >= 21.2.22, or >= 20.3.30) if available for your specific branch, or migrate to a secure version. - Audit application code for usage of
document.createProcessingInstructionorRenderer2DOM insertion methods, specifically looking for instances where user-supplied strings are passed to thedataparameter. - Implement strict input validation or manual escaping of the
<character for any untrusted data destined forProcessingInstructionnodes on the server until the software is patched.
Immediate actions
Upgrade platform-server to 20.3.30 or later
Mitigations
Review codebase for usages of createProcessingInstruction and sanitize input strings by encoding '<' characters.
CVE-2026-88058