The vulnerability lies in the domino library, a dependency of @angular/platform-server, used for DOM emulation during Server-Side Rendering (SSR). The root cause is the improper handling of <noscript> elements. When scripting is enabled in domino (as it is in Angular SSR), <noscript> is treated as a raw-text element, meaning its content should not be parsed as HTML. However, the serializer failed to escape closing </noscript> tags (</noscript>) within the element's content.
The analysis of the patch commits reveals two key functions involved:
-
serializeOne in lib/NodeUtils.js: This is the primary vulnerable function. It orchestrates the serialization of DOM nodes. Before the patch, it lacked the logic to identify that <noscript> content required escaping when scripting was enabled. An attacker could provide a string like </noscript><script>alert(1)</script> as input, and serializeOne would fail to escape the closing </noscript> tag, leading to the premature termination of the <noscript> block in the browser and the execution of the injected script.
-
escapeMatchingClosingTag in lib/NodeUtils.js: This function performs the actual escaping of closing tags. While the primary fault was in serializeOne not calling it for <noscript>, this function itself was also found to be flawed. It did not correctly handle strings containing astral (multi-byte) Unicode characters, which could cause the escaping to fail. This was a secondary bug that was fixed as part of the overall patch.
Therefore, during exploitation, a call to serializeOne would be made to render the malicious content inside a <noscript> tag. This function, in its vulnerable state, would not correctly process the content, leading to the XSS vulnerability.