Listen to this Post
The vulnerability arises from a UTF-16 index alignment bug in the `domino` library, which Angular uses for server-side DOM emulation during SSR. When serializing raw-text elements like <script>, <style>, or <iframe>, `domino` attempts to escape any closing tags (e.g., </script>) found inside the element’s content. However, JavaScript measures string indices in UTF-16 code units – astral characters (e.g., emojis, 😀) occupy two code units instead of one. If an attacker injects dynamic text that includes an astral character immediately before a raw closing tag, domino’s index offset calculation misaligns. The escaping logic then fails to recognize or replace the closing tag, leaving it unescaped in the final HTML output. When the browser parses this SSR-generated page, the unescaped closing tag prematurely closes the raw-text context, allowing the attacker’s subsequent `` inside an `
DailyCVE Form:
Platform: Angular Universal
Version: <19.2.25, <20.3.24, <21.2.16, <22.0.0-rc.2
Vulnerability: Unicode index misalignment
Severity: High (XSS)
date: 2023-10-18
Prediction: Already patched
What Undercode Say:
Check vulnerable Angular versions
npm list @angular/platform-server | grep -E "19.[0-2].[0-9]{1,2}|20.[0-2].[0-9]{1,2}|21.[0-1].[0-9]{1,2}"
Test payload for local SSR
curl -X POST https://your-ssr-site.com/iframe-content -d "data=😀</iframe><script>alert(document.cookie)</script>"
// Simulate domino misalignment in Node
const domino = require('domino');
const doc = domino.createDocument('
<iframe>INJECT</iframe>
');
doc.querySelector('iframe').textContent = '😀</iframe><script>alert(1)</script>';
console.log(doc.serialize()); // unescaped closing tag appears
Exploit:
Attacker controls any text bound inside <iframe>, <script>, or `
