Skip to main content

Angular Platform-Server CVE-2026-50555

| EUVDEUVD-2026-38289 HIGH
Cross-site Scripting (XSS) (CWE-79)
2026-06-15 https://github.com/angular/angular GHSA-hqr9-c56f-3x7f
8.6
CVSS 4.0 · Vendor: https://github.com/angular/angular
Share

Severity by source

Vendor (https://github.com/angular/angular) PRIMARY
8.6 HIGH
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/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
vuln.today AI
6.1 CRITICAL

Network-reachable SSR endpoint, no auth, low complexity; victim must load the rendered page (UI:R); script executes in a different security context than the vulnerable server (S:C) with limited XSS-typical C/I impact and no availability impact.

3.1 AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
4.0 AV:N/AC:L/AT:N/PR:N/UI:P/VC:L/VI:L/VA:N/SC:H/SI:H/SA:N

Primary rating from Vendor (https://github.com/angular/angular).

CVSS VectorVendor: https://github.com/angular/angular

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/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
P
Scope
X

Lifecycle Timeline

6
Analysis Updated
Jun 22, 2026 - 18:33 vuln.today
v3 (cvss_changed)
Analysis Updated
Jun 22, 2026 - 18:32 vuln.today
v2 (cvss_changed)
Re-analysis Queued
Jun 22, 2026 - 18:23 vuln.today
cvss_changed
CVSS changed
Jun 22, 2026 - 18:23 NVD
8.6 (HIGH)
Source Code Evidence Fetched
Jun 15, 2026 - 17:51 vuln.today
Analysis Generated
Jun 15, 2026 - 17:51 vuln.today

DescriptionCVE.org

A Cross-Site Scripting (XSS) vulnerability exists in @angular/platform-server's DOM emulation dependency (domino) when serializing the content of raw-text elements (such as <script>, <style>, and <iframe>).

domino supports escaping raw-text elements during serialization to prevent closing-tag breakout. However, a Unicode index alignment bug existed in this escaping logic.

In JavaScript, string lengths and character indices are calculated based on UTF-16 code units (where astral characters-such as emojis-occupy 2 code units / 4 bytes). If the bound dynamic text contained astral Unicode characters _before_ the closing tag (e.g. </script>, </style>, or </iframe>), the index offset calculation in domino's replacement logic shifted.

This misalignment caused domino to fail to replace or escape the closing tag, leaving it raw and unescaped in the output HTML.

An attacker who controls the dynamic text can supply a payload containing both an astral Unicode character and a closing tag (e.g., 😀</iframe><script>alert(1)</script>). When serialized on the server during SSR, the browser parses the unescaped closing tag, exits the raw-text context early, and executes the subsequent <script> block, leading to same-origin Cross-Site Scripting (XSS).

Impact

This vulnerability allows an attacker to perform same-origin Cross-Site Scripting (XSS) attacks against any user visiting an SSR-rendered page that binds user-controlled data inside raw-text elements. This can lead to session hijacking, credentials theft, unauthorized actions on behalf of users, and defacement.

Patched Versions

  • 22.0.0-rc.2
  • 21.2.16
  • 20.3.24
  • 19.2.25

Workarounds

If you cannot immediately update your dependencies, you can:

  • Avoid binding user-controlled values inside <iframe> or other raw-text elements.
  • Sanitize any user input placed inside raw-text elements to explicitly strip closing tags before passing it to the template.

AnalysisAI

Same-origin Cross-Site Scripting in @angular/platform-server (SSR) allows attackers who control bound dynamic text inside raw-text elements (script, style, iframe, noscript) to break out of the raw-text context and execute arbitrary JavaScript in the victim's browser. The root cause is a Unicode index-alignment bug in the bundled domino DOM library: astral characters (e.g. emojis) before a closing tag shift the replacement offset, leaving the closing tag unescaped. Publicly available exploit code exists in the upstream PR's regression tests, but there is no public exploit identified in the wild and the CVE is not on CISA KEV.

Technical ContextAI

@angular/platform-server is Angular's server-side rendering (SSR) engine; it uses the domino library to provide a server-side DOM. Per HTML serialization rules, raw-text elements (script, style, iframe, noscript) cannot contain entity references, so domino instead defensively escapes any literal closing tag (e.g. </iframe>) appearing inside the text node. The buggy implementation in lib/NodeUtils.js spread the text into an array of code points ([...rawText]) and then indexed it using RegExp.matchAll(...).index, which returns UTF-16 code-unit offsets. Astral characters (U+10000 and above) occupy two UTF-16 code units but only one code-point slot, so each one before the match shifted the replacement target by one position, causing the wrong character to be replaced and the real </tag> to survive. This is a textbook CWE-79 (Improper Neutralization of Input During Web Page Generation) caused by an encoding/indexing mismatch rather than missing sanitization. The fix replaces the array-and-index approach with String.prototype.replace, which is encoding-agnostic, and additionally treats <noscript> as a raw-content element on serialization.

RemediationAI

Vendor-released patch: upgrade @angular/platform-server to 22.0.0-rc.2, 21.2.16, 20.3.24, or 19.2.25 depending on the major version line in use; the fix is implemented in angular/domino PR #29 (https://github.com/angular/domino/pull/29) and shipped via the Angular GHSA at https://github.com/angular/angular/security/advisories/GHSA-hqr9-c56f-3x7f. If you cannot upgrade immediately, audit templates and stop binding user-controlled values inside raw-text elements (<iframe>, <script>, <style>, <noscript>) - these are unusual bindings to begin with; the trade-off is removing or relocating that dynamic content to a normal element body where Angular interpolation safely escapes it. As a second compensating control, pre-process any user input destined for raw-text element content to strip or escape literal closing-tag prefixes (e.g. replace </iframe, </script, </style, </noscript case-insensitively with their entity-escaped form) before passing it to the template; this is brittle and must cover every raw-text tag, so it should only be a stopgap until packages are updated.

Share

CVE-2026-50555 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy