CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-88058

CVE-2026-88058: Cross-Site Scripting via Server-Side Serialization Discrepancy in @angular/platform-server

Alon Barad
Alon Barad
Software Engineer

Sep 29, 2026·9 min read·35 visits

Executive Summary (TL;DR)

An unauthenticated attacker can achieve arbitrary JavaScript execution in a victim's browser by injecting closing tags into ProcessingInstruction nodes processed during server-side rendering, exploiting an escaping discrepancy in Angular's DOM emulator.

A high-severity Cross-Site Scripting (XSS) vulnerability in Angular server-side rendering (SSR) component allows unauthenticated attackers to execute arbitrary client-side JavaScript. The flaw is caused by a parsing discrepancy between the server-side DOM emulator, Domino, and standard client-side browser HTML5 parsers. When serializing ProcessingInstruction nodes inside raw-content fallback elements, Domino fails to escape matching ancestor closing tags, causing the client-side parser to transition out of raw-text mode prematurely and execute subsequent sibling elements as active HTML.

Vulnerability Overview

Angular Server-Side Rendering (SSR) utilizes the @angular/platform-server package to bootstrap and execute applications on a server-side environment before delivering the finalized HTML to the client browser. To emulate standard browser Document Object Model (DOM) behaviors on the server, the framework integrates Domino, a lightweight server-side DOM implementation. During the lifecycle of an SSR request, Domino manages the virtual DOM and eventually serializes the fully constructed tree into a single raw HTML output string. This output string is then delivered over the network to the victim browser, which parses it as standard HTML5 markup.

The critical vulnerability identified as CVE-2026-88058 arises from a context-dependent parsing discrepancy between the server-side Domino serializer and the client-side browser tokenizer. The flaw manifests when processing fallback raw-content elements, including <noscript>, <iframe>, <noembed>, and <noframes>. Specifically, Domino's HTML serialization engine fails to properly escape or sanitize ProcessingInstruction DOM nodes (nodeType === 7) when they are nested inside these raw-content containers. If an attacker controls the data payload of these nodes, they can craft an injection that forces the client browser to prematurely terminate the raw-content container and interpret subsequent text as active HTML.

While standard Angular template compilers restrict the creation of arbitrary processing instructions, application-specific code or third-party libraries may bypass these constraints. Developers often utilize DOM-manipulation techniques, such as injecting raw-content fragments or programmatically creating nodes via inject(DOCUMENT).createProcessingInstruction(). If the data supplied to these APIs is derived from untrusted user input without thorough server-side sanitization, an attacker can manipulate the generated DOM tree structure. Consequently, the resulting serialization output allows for full Cross-Site Scripting (XSS) vulnerabilities inside the browser environment.

Root Cause Analysis

To understand the technical cause of CVE-2026-88058, it is necessary to examine the HTML5 specification tokenizer states for raw-content container tags. When a standard browser parser encounters raw-content container tags such as <noscript>, it transitions its internal tokenizer into the RAWTEXT state. In this specialized state, the parser does not recognize standard HTML tags, delimiters, or elements like comments and processing instructions. Instead, it reads all characters as literal text until it encounters a case-insensitive matching end tag sequence, such as </noscript>. This design ensures that raw code block contents are not inadvertently interpreted as active HTML markup.

Conversely, when Domino acts as the server-side DOM emulator, it processes processing instruction nodes as distinct DOM components, irrespective of their parent elements. During serialization, Domino converts these nodes into processing instruction strings bounded by <? and ?> characters. Because Domino's original implementation only escaped the greater-than character (>) to &gt; inside the data field of these instructions, it left less-than characters (<) unmodified. This incomplete escaping mechanism becomes problematic when a processing instruction containing a sequence like </noscript is nested inside a <noscript> container.

When the client-side browser receives the serialized HTML, it starts tokenizing the container in the RAWTEXT state. Because it is in RAWTEXT mode, the browser ignores the starting boundary of the processing instruction (<?) and continues consuming data until it parses the nested </noscript sequence. According to the HTML5 specification, the trailing space in </noscript satisfies the end tag token requirement, prompting the tokenizer to exit RAWTEXT mode and return to the default Data state. The subsequent characters, including any attacker-controlled element like a malicious image tag, are then interpreted as live HTML elements, resulting in arbitrary code execution.

Code-Level Deep Dive

The vulnerability in Domino is located within the node serialization logic, specifically in the serializeOne() function of the lib/NodeUtils.js module. In older versions of the library, the serializer handled processing instruction nodes (case 7) by applying a basic escaping function to the node data before outputting the serialized tag. The function escapeProcessingInstructionContent() only converted > to &gt;, ignoring < characters. Because the serializer did not examine the tag's ancestors, it could not determine whether the node was located within a raw-content container that would trigger RAWTEXT parsing in the browser.

Furthermore, the vulnerability was compounded by an architectural limitation in how Domino parsed nested document fragments. When Angular compiled elements within a DOCUMENT_FRAGMENT_NODE (such as inside <template> contexts), the fragments did not maintain a functional parentNode relationship linking back to their parent elements. This caused Domino's upward tree-climbing function, fallbackRawContentTags(), to fail when attempting to resolve ancestors past the fragment boundaries. As a result, processing instructions nested inside template fragments escaped detection, preventing any context-aware serialization from occurring.

To resolve this issue, the maintainers modified several core modules in Domino. In lib/htmlelts.js, the HTMLTemplateElement constructor was updated to define a hidden _host property that references the template parent element, allowing fragments to preserve a path to their host. In lib/NodeUtils.js, the fallbackRawContentTags() function was rewritten to detect the _host property on DOCUMENT_FRAGMENT_NODE instances and traverse upward past fragment boundaries. Finally, the serializer in serializeOne() was patched to check if processing instruction content contains the </ sequence; if present, the engine dynamically resolves all raw-content ancestors and escapes matching closing tags using the escapeMatchingClosingTag() function.

// Fragment of the patched serializeOne function inside Domino:
case 7: // PROCESSING_INSTRUCTION_NODE
  let content = escapeProcessingInstructionContent(kid.data);
  if (content.includes('</')) {
    // Resolve all active raw content fallback tags up the DOM chain
    const fallbackTags = fallbackRawContentTags(parent);
    for (const fallbackTag of fallbackTags) {
      // Escape any occurrences of matching closing sequences
      content = escapeMatchingClosingTag(content, fallbackTag);
    }
  }
  s += '<?' + kid.target + ' ' + content + '?>';
  break;

Exploitation Methodology

Exploitation of CVE-2026-88058 requires an environment where an attacker can supply input to a programmatically generated ProcessingInstruction node. The vulnerability cannot be triggered via standard static Angular template definitions, which do not natively support processing instruction compilation. Instead, the attacker targets custom application components, dynamic page-rendering engines, or third-party libraries that use the Renderer2 API or DOCUMENT token to construct DOM nodes dynamically. The attack flow begins when the server accepts un-sanitized input, such as a query parameter or header, and assigns it to a newly created processing instruction.

The attacker crafts a payload that includes a container breakout sequence followed by a malicious HTML element, such as </noscript><img src=x onerror=alert(1)>. On the server, the application executes standard SSR rendering routines, creating a <noscript> container and nesting the processing instruction inside it. When Domino serializes the virtual DOM tree, it outputs the sequence <noscript><?x </noscript ?><img src="x" onerror="alert(1)"></noscript>. Note that because the payload contains no > characters before the breakout tag, the legacy serializer emits the sequence unmodified, failing to neutralize the <noscript closing sequence.

When the victim loads the resulting web page, their browser begins parsing the server-rendered HTML document. The browser encounters the <noscript> tag and enters RAWTEXT parsing mode, treating the subsequent content as literal character data. However, as soon as the tokenizer parses the </noscript sequence, it recognizes a valid container-ending token and exits RAWTEXT mode. The browser then treats the trailing ?><img src="x" onerror="alert(1)"> as standard HTML markup, executing the JavaScript payload within the security context of the victim's session.

Impact and Threat Analysis

The impact of CVE-2026-88058 is classified as high because successful exploitation leads to full Cross-Site Scripting (XSS) in the victim's browser context. An attacker who successfully exploits this vulnerability can execute arbitrary JavaScript code within the session of any user who visits the rendered page. This capability permits the unauthorized extraction of session identifiers, authentication tokens, and sensitive data stored in local storage or cookies. Additionally, the attacker can perform unauthorized actions on behalf of the victim, such as initiating transactions or modifying account settings.

Because the vulnerability occurs during Server-Side Rendering, the malicious payload is delivered directly within the initial HTML payload sent by the server. This transmission mechanism can bypass some basic client-side detection vectors, as the payload is parsed and executed immediately during the initial page-render lifecycle. According to the CVSS v4.0 metrics, this flaw has been assigned a base score of 8.6, reflecting the high confidentiality and integrity impact on the client-side system. The threat landscape is further influenced by the low attack complexity and the lack of authentication requirements needed to deliver the exploit payload.

While the EPSS score indicates a relatively low probability of active exploitation in the wild, the vulnerability remains a significant threat to applications utilizing Angular SSR. Since Angular applications often process highly sensitive business logic, an XSS exploit can compromise administrative interfaces and orchestrate broader lateral movement attacks. Security teams must treat the issue with high priority, especially in applications that render untrusted user data within custom server-side layout managers.

Remediation and Defensive Strategy

The primary remediation for CVE-2026-88058 is to upgrade @angular/platform-server and the underlying domino package to patched versions. The vulnerability has been resolved in the Angular release tracks 20.x, 21.x, and 22.x, with specific secure releases designated as 20.3.30, 21.2.22, and 22.1.4 respectively. Organizations must update their package manifests and rebuild their applications to apply the patches. Additionally, developers should audit their package lockfiles to verify that the transitive domino dependency resolves to a version incorporating the fix committed in the upstream repository.

If immediate upgrading is not feasible due to legacy constraints or deployment cycles, development teams should implement strict input validation on all data passed to DOM-generation APIs. Specifically, any string supplied to createProcessingInstruction() or custom DOM manipulation routines must be validated to prevent the inclusion of HTML delimiter characters. Implementing a robust Content Security Policy (CSP) provides an additional layer of defense by restricting inline script execution and limiting the impact of any successful injection. A restrictive CSP can block unauthorized script execution even if an attacker successfully injects elements into the page markup.

Finally, development teams must conduct systematic code reviews to identify patterns where raw DOM APIs are used in server-side contexts. Security auditors should pay special attention to sections of code where the DOCUMENT injection token or Renderer2 are used to construct processing instructions or fallback raw-content elements. Ensuring that all dynamic content is bound using standard Angular data-binding patterns, which automatically apply contextual escaping, significantly reduces the application's attack surface.

Official Patches

AngularOfficial Angular Security Advisory
DominoUpstream fix in Domino repository

Fix Analysis (3)

Technical Appendix

CVSS Score
8.6/ 10
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
EPSS Probability
0.88%
Top 17% most exploited

Affected Systems

@angular/platform-serverdomino

Affected Versions Detail

Product
Affected Versions
Fixed Version
@angular/platform-server
Angular
>= 20.0.0, < 20.3.3020.3.30
@angular/platform-server
Angular
>= 21.0.0, < 21.2.2221.2.22
@angular/platform-server
Angular
>= 22.0.0, < 22.1.422.1.4
domino
Angular
< 2.1.72.1.7 (Commit 04f987dc08ff3736b427f50941adf1722458528f)
AttributeDetail
CWE IDCWE-79
Attack VectorNetwork
CVSS Base Score8.6
EPSS Score0.00875
ImpactArbitrary Client-Side Code Execution (XSS)
Exploit Statuspoc
KEV StatusNot Listed
Target ComponentDomino HTML Serializer inside @angular/platform-server

MITRE ATT&CK Mapping

T1189Drive-by Compromise
Initial Access
T1185Browser Session Hijacking
Collection
CWE-79
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

The application does not neutralize or incorrectly neutralizes user-controlled input before it is placed in output that is used as a web page that is served to other users.

Known Exploits & Detection

GitHub Issue #70146Original bug report with comprehensive details explaining how nested templates bypass the serialization ancestor tree walk.

Vulnerability Timeline

Vulnerability identified and reported as Issue #70146 in the Angular tracker.
2026-08-11
Remediation patch committed to domino and lock files updated in angular repository.
2026-08-20
Security Advisory GHSA-j3r3-mxqp-r2p4 and CVE-2026-88058 published.
2026-09-10
National Vulnerability Database (NVD) record updated with severity rankings.
2026-09-11

References & Sources

  • [1]GitHub Security Advisory GHSA-j3r3-mxqp-r2p4
  • [2]Official CVE Record
  • [3]Angular Issue Tracking #70146
  • [4]NVD Vulnerability Details
  • [5]Domino Patch Commit
  • [6]Angular Integration Commit (v22/Main)
  • [7]Angular Integration Commit (v21/v20)
  • [8]Angular Release v22.1.4
  • [9]Angular Release v21.2.22
  • [10]Angular Release v20.3.30

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•10 minutes ago•CVE-2026-126084
4.7

CVE-2026-126084: Unsigned Content-Type in Rails Active Storage GCS Direct Uploads

A vulnerability classified under CWE-345 (Insufficient Verification of Data Authenticity) exists in the Active Storage component of Ruby on Rails prior to versions 8.1.4.1 and 8.0.5.2. When Google Cloud Storage (GCS) is configured as the storage backend with the cache_control option enabled, Active Storage switches from GCS V2 signing to V4 signing for direct upload URLs. Because the V4 signing implementation only binds the Cache-Control and Host headers, the Content-Type and Content-MD5 headers remain unsigned. An attacker can modify the Content-Type header during a direct upload request to store HTML or SVG files with active JavaScript on the GCS bucket origin, enabling Service Worker registration and interception of subsequent signed URL responses within the bucket path.

Amit Schendel
Amit Schendel
0 views•9 min read
•about 1 hour ago•CVE-2026-126079
6.1

CVE-2026-126079: Cross-Site Scripting in Ruby on Rails Action View Text Helpers via HTML5 Serialization Desynchronization

A Cross-Site Scripting (XSS) vulnerability exists in Ruby on Rails Action View prior to versions 8.0.5.2 and 8.1.4.1. When applications use the default HTML5 sanitizer (Rails::HTML5::Sanitizer) with Nokogiri versions prior to 1.19.5, angle brackets (< and >) inside HTML attribute values are serialized unescaped. Action View text helpers—specifically highlight and simple_format—perform string-based manipulations on the sanitized HTML rather than operating on the DOM tree. An unescaped '>' character or a double newline ('\n\n') inside an attribute value causes these helpers to misidentify tag or paragraph boundaries, breaking out of the attribute context and emitting inert attribute contents as live HTML elements in the final html_safe output.

Amit Schendel
Amit Schendel
2 views•10 min read
•about 2 hours ago•CVE-2026-126070
6.1

CVE-2026-126070: Cross-Site Scripting in Ruby on Rails Action View strip_tags Helper

CVE-2026-126070 is a Cross-Site Scripting (XSS) vulnerability in the Action View component of Ruby on Rails. Prior to versions 8.0.5.2 and 8.1.4.1, the strip_tags helper returned sanitized output marked as html_safe without encoding single or double quotation marks. When applications render the output of strip_tags inside quoted HTML attributes in ERB templates, attackers can break out of the attribute context and inject arbitrary HTML attributes or JavaScript event handlers.

Amit Schendel
Amit Schendel
3 views•10 min read
•about 3 hours ago•CVE-2026-126078
6.1

CVE-2026-126078: Cross-Site Scripting in Ruby on Rails Action View highlight Helper

CVE-2026-126078 is a Cross-Site Scripting (XSS) vulnerability classified under CWE-79 affecting the Action View component of Ruby on Rails in versions prior to 8.0.5.2 and 8.1.4.1. The vulnerability resides in the ActionView::Helpers::TextHelper#highlight method when invoked with a custom :highlighter template that places capture group placeholders inside HTML attribute values. Because matched substrings are substituted without HTML escaping after initial sanitization preserves literal quotation marks, an attacker controlling the input text or target search phrase can break out of the surrounding attribute delimiter and inject arbitrary HTML attributes or JavaScript event handlers.

Amit Schendel
Amit Schendel
3 views•9 min read
•about 4 hours ago•CVE-2026-126077
6.8

CVE-2026-126077: Session Information Leak in Ruby on Rails Action Pack and Active Storage Proxy Mode

An information exposure vulnerability in Ruby on Rails Action Pack allows sensitive session cookies to be attached to public, cacheable responses served by Active Storage proxy controllers. When cookie secret rotation or a hybrid cookie serializer migration is enabled, reading a legacy-format cookie triggers an automatic cookie rewrite that ignores the session-skipping directive. If an intermediate shared cache or CDN caches the resulting response along with its Set-Cookie header, subsequent users requesting the same URL receive the leaked session token.

Amit Schendel
Amit Schendel
3 views•11 min read
•about 5 hours ago•CVE-2026-126072
5.9

CVE-2026-126072: Thread Deadlock and Denial of Service in Ruby on Rails ActionController::Live

CVE-2026-126072 (GHSA-rwvh-fw6r-pwvp) is a concurrency deadlock vulnerability in the Ruby on Rails Action Pack framework affecting applications that utilize ActionController::Live response streaming. The defect occurs due to improper synchronization within ActionController::Live::Buffer when handling full bounded queues during stream closure and connection abortion. An unauthenticated remote attacker can trigger this condition by stalling TCP socket reads on streaming endpoints—including Active Storage proxy mode—resulting in permanent worker thread exhaustion and application-wide denial of service.

Amit Schendel
Amit Schendel
3 views•10 min read