Security
Jun 12, 2026

CVE-2026-50555 & CVE-2026-50556 - Two High-Severity XSS Vulnerabilities in Angular SSR's DOM Serialization Layer

Inside the two server-side rendering XSS vulnerabilities affecting Angular 19 through 22, and why EOL versions can't patch

Give me the TL;DR
CVE-2026-50555 & CVE-2026-50556 - Two High-Severity XSS Vulnerabilities in Angular SSR's DOM Serialization Layer
For Qualys admins, NES for .NET directly resolves the EOL/Obsolete Software:   Microsoft .NET Version 6 Detected vulnerability, ensuring your systems remain secure and compliant. Fill out the form to get pricing details and learn more.

Two High-severity Cross-Site Scripting vulnerabilities (XSS), CVE-2026-50555 and CVE-2026-50556, have been disclosed in @angular/platform-server. Both originate in the same underlying component domino, the server-side DOM emulator that Angular's Server-Side Rendering (SSR) engine uses to serialize rendered HTML before sending it to the browser. Both allow an attacker who can influence server-rendered content to inject and execute arbitrary JavaScript in the context of a user's browser session. Both carry a CVSS v4 score of 8.6 High.

The two vulnerabilities are distinct in their triggering element and root cause, but they are disclosed simultaneously, affect the same package and version ranges, and are resolved by the same set of patched releases. This post covers both. The version impact and affected element types differ between them, and those differences are called out explicitly in each section.

Patched versions are available for Angular 19 through 22 pre-release. Angular 18 reached end-of-life (EOL) in November 2024 and the Angular project does not generally issue security fixes for EOL releases.

What Are CVE-2026-50555 and CVE-2026-50556?

Both vulnerabilities are XSS flaws in how Angular's server-side rendering layer serializes dynamic content into HTML. During SSR, Angular uses domino to emulate a browser DOM on the server. When the rendered page is serialized to an HTML string and sent to the client, domino is responsible for correctly escaping dynamic values so that user-controlled content cannot break out of the element it belongs to and inject new HTML structure. Both CVEs represent failures of that escaping logic for specific element types.

CVE-2026-50555 -  A Unicode index alignment bug in domino's closing-tag escaping logic for raw-text elements including <script>, <style>, and <iframe>. When dynamic text bound into one of these elements contains an astral Unicode character, such as an emoji, before a closing tag, JavaScript's UTF-16 string indexing causes an offset miscalculation. The escaping logic targets the wrong character position, the closing tag is left unescaped in the serialized output, and the browser parses it as literal HTML rather than text content.

CVE-2026-50556 -  A complete omission of <noscript> from domino's list of raw-text elements that require closing-tag escaping. Under SSR, domino operates with scripting enabled, which means <noscript> is treated as a raw-text element whose content should not be parsed as HTML. The serializer, however, never included <noscript> in the set of elements subject to closing-tag escaping. Any occurrence of </noscript> in user-controlled content bound inside a <noscript> element passes through to the output unescaped, under all circumstances, regardless of whether astral characters are present.

In both cases, the mechanism of exploitation is the same. The unescaped closing tag in the server-rendered HTML closes the raw-text element early. Content that follows, including attacker-supplied <script> blocks, is then parsed and executed by the browser in the same-origin context as the application.

CVE-2026-50555 and CVE-2026-50556 — CVSS v4 8.6 (High) Vector: 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

Both vulnerabilities share the same score and vector. An attacker can exploit them remotely without any special access or credentials — the only requirement is that a user visits the affected page. Once that happens, the attacker's script runs in the victim's browser as if it were a legitimate part of the application, giving it access to the user's session, cookies, and application data. This is what drives the High rating for both confidentiality and integrity.

Why Angular SSR XSS Is a Distinct Risk Category

XSS vulnerabilities in server-side rendered applications carry a different risk profile than those in purely client-side applications. In a client-side Angular app, the template compiler sanitizes dynamic values before they reach the DOM, and the browser never receives raw unsanitized markup. In an SSR application, the serialization step happens on the server, before the browser is involved. If the serializer emits unsafe HTML, that HTML arrives in the initial page load as part of the server's response, not as a subsequent client-side DOM manipulation.

That distinction matters for two reasons. First, the injected script executes immediately on page load, before any client-side JavaScript has run, before Angular has hydrated, and before any runtime sanitization can intervene. Second, the injected content is present in the raw HTML response, which means it is visible to scanners, crawlers, and caches. A page cached by a CDN with injected content serves that content to every user who receives the cached response, not just the user whose request triggered the injection.

The consequences of a successful exploit include session hijacking through cookie theft, credential exfiltration through form overlay or network interception, unauthorized actions taken on behalf of authenticated users, and page defacement. For applications in regulated industries, a demonstrated XSS in a server-rendered page is a material finding in SOC 2, PCI DSS, and ISO 27001 assessments.

Dependency scanners including Snyk and Tenable will flag both CVE-2026-50555 and CVE-2026-50556 against any @angular/platform-server version in the affected ranges. Teams running Angular SSR on EOL versions will see two open High-severity findings with no upstream path to resolution.

Who Is Affected

Both CVE-2026-50555 and CVE-2026-50556 affect applications using @angular/platform-server for server-side rendering where user-controlled data is bound into template content that reaches the serialization layer. Angular applications running entirely in the browser without SSR are not affected.

The specific triggering conditions differ slightly between the two CVEs:

  • CVE-2026-50555 requires user-controlled content bound inside a <script>, <style>, or <iframe> element in an SSR template, where that content contains an astral Unicode character (such as an emoji or supplementary plane character) followed by a closing tag for that element.
  • CVE-2026-50556 requires user-controlled content bound inside a <noscript> element in an SSR template, where that content contains a </noscript> closing tag. No astral characters are required. The escaping gap is unconditional for this element.

The single patch pull request (angular/domino#29) resolves both CVE-2026-50555 and CVE-2026-50556 simultaneously. 

Angular 19 reached end-of-life on May 19, 2026. The upstream team published 19.2.25 as part of this disclosure. The advisory lists "n/a" as the patched version for the <= 18.2.14 range for both CVEs.

Why Upgrading Is Not a Short-Term Fix for EOL Versions

For teams on Angular 20 or 21, the remediation is a patch update. For teams on Angular 18 or earlier, there is no upstream fix and the Angular team will most likely not provide one. That is the EOL policy, applied consistently regardless of CVE severity.

Upgrading an SSR application from Angular 17 or 18 to Angular 20 or 21 is not a minor version bump. Angular's SSR architecture has changed significantly across recent major versions: the introduction of @angular/ssr as a distinct package, the shift from renderModule patterns to renderApplication, the integration of hydration and HttpTransferCache, and the move to the esbuild-based application builder all land across the major version boundaries that EOL teams would need to cross. The right migration path exists and is well-documented. It takes time that most production teams managing live SSR applications do not have in a 30 to 90 day audit window.

In the meantime, two open High-severity XSS findings on a production SSR deployment are not background noise. They appear on scanner dashboards, they appear in penetration test reports, and they appear in compliance audit findings. A plan to upgrade does not close a finding. A patched package version does.

Technical Breakdown

CVE-2026-50555 Unicode Index Alignment Bug in Raw-Text Element Escaping

Angular's SSR engine uses domino to emulate a browser DOM on the server. When the DOM is serialized to HTML, domino applies escaping to the content of raw-text elements to prevent closing-tag breakout. For elements like <script>, <style>, and <iframe>, any occurrence of the element's own closing tag in the content must be escaped so the browser does not interpret it as the actual end of the element.

The escaping logic operates by scanning the content string for the closing tag and computing character positions to apply the replacement. The bug is in that index computation. JavaScript strings are sequences of UTF-16 code units. Characters from Unicode's Basic Multilingual Plane occupy one code unit each. Characters outside the BMP, including emoji and many supplementary characters, occupy two code units: a surrogate pair. JavaScript's String.length and index-based operations count code units, not Unicode codepoints.

When user-controlled content contains an astral character (two code units) before the closing tag, the index calculation in domino's replacement logic treats the surrogate pair as a single character. The computed offset for where the closing tag begins is one position off. The replacement targets the wrong characters, the closing tag survives in the serialized output unescaped, and the browser closes the raw-text element at that position. Any content the attacker appended after the closing tag, including a <script> block, executes in the page context.

A minimal payload triggering CVE-2026-50555 against an <iframe> binding would be content such as 😀</iframe><script>alert(1)</script>. The emoji provides the astral character that shifts the index, and the rest exploits the resulting escaping gap.

CVE-2026-50556: Missing <noscript> Escaping in domino's Serializer

The root cause of CVE-2026-50556 is simpler: domino's serializer maintained an explicit list of raw-text elements whose closing tags require escaping during serialization, and <noscript> was never added to that list.

Under normal browser conditions with scripting enabled, <noscript> content is not parsed as HTML, it is inert. But domino runs on the server with scripting enabled. In that context, the HTML parsing specification treats <noscript> as a raw-text element during serialization: its content should be opaque text that is not interpreted as markup. domino's serializer recognized this for <script>, <style>, and others, but not for <noscript>.

The result is that any </noscript> substring in user-controlled content bound into a <noscript> template element passes through to the serialized HTML completely unescaped. No astral characters are required. No special encoding is needed. The payload </noscript><script>alert(1)</script> is sufficient. When the browser parses the server response, it sees the closing tag, exits the <noscript> context, and executes the injected script.

The fix in angular/domino#29 adds noscript to the serializer's raw-text element list and corrects the UTF-16 index calculation for CVE-2026-50555, resolving both vulnerabilities in the same change.

Interim Workarounds

If you cannot update immediately, both advisories recommend the same category of workaround: avoid binding user-controlled values inside the affected elements, and sanitize any user input that must reach those elements to strip the relevant closing tags before the value reaches the template.

For CVE-2026-50555, strip or encode </script>, </style>, and </iframe> substrings from user input before binding it inside those elements on the server.

For CVE-2026-50556, strip or encode </noscript> substrings from user input before binding it inside <noscript> elements.

These workarounds reduce exposure at the application layer but do not resolve the underlying serializer bug. They are stopgaps, not substitutes for patched packages. Application-layer sanitization also depends on every code path that reaches the affected binding being correctly identified and hardened, which is difficult to guarantee in complex SSR applications.

The HeroDevs Solution

NES for Angular includes @angular/platform-server across all supported EOL versions, from Angular 4 through Angular 19. For teams on Angular 18 or earlier, NES resolves both CVE-2026-50555 and CVE-2026-50556 as drop-in replacements, with no template changes, no server entry point refactoring, and no build configuration changes required.

The update path is the same as any NES package update, configure the NES registry token, update the @angular/platform-server reference in your package.json to the corresponding NES version, and rebuild. The patched NES package is a direct replacement for the EOL OSS package at your current version line. Your SSR rendering pipeline is unchanged.

NES packages are recognized by Snyk, Tenable, and other major dependency scanners. Both CVE-2026-50555 and CVE-2026-50556 are resolved in a single NES package update. Letters of attestation are available for auditors or customers requiring documented remediation evidence. HeroDevs is a CVE Numbering Authority (CNA).

Taking Action

Angular 21.x SSR -  Update @angular/platform-server to 21.2.16. Both CVE-2026-50555 and CVE-2026-50556 are resolved. Review your SSR templates for any bindings that place user-controlled content inside <script>, <style>, <iframe>, or <noscript> elements and confirm those bindings are intentional.

Angular 20.x SSR -  Update to 20.3.24. Same guidance applies.

Angular 19.x SSR -  Update to 19.2.25. Angular 19 is EOL as of May 2026. Plan your migration to Angular 20 or 21, or engage NES for Angular 19 to receive continued security coverage beyond EOL.

Angular 18.x and earlier SSR -  No upstream patch exists for either CVE. Apply the interim workarounds to reduce immediate exposure. Contact HeroDevs to access the remediated NES package for your Angular version. A single NES package update resolves both vulnerabilities.

Learn more about NES for Angular, or visit the HeroDevs vulnerability directory for the full list of CVEs and advisories affecting EOL Angular versions.

Table of Contents
Author
Ryan Jasinski
Engineering Manager
Open Source Insights Delivered Monthly