CVE-2026-54267 Overview
CVE-2026-54267 is a DOM Clobbering vulnerability in Angular's Server-Side Rendering (SSR) hydration mechanism. The flaw exists in the TransferState restoration logic used by provideClientHydration(). Angular locates the serialized server state by calling document.getElementById('ng-state') without verifying the element type. Attackers who can inject element attributes such as id through untrusted user input or CMS content can clobber this lookup. The browser then returns an attacker-controlled element, which Angular parses as JSON during hydration. The vulnerability is tracked under [CWE-79] and is fixed in Angular versions 22.0.1, 21.2.17, and 20.3.25.
Critical Impact
An attacker controlling DOM element attributes can hijack Angular's hydration state, leading to client-side script execution and tampering of cached HttpClient responses.
Affected Products
- Angular versions prior to 22.0.1
- Angular versions prior to 21.2.17
- Angular versions prior to 20.3.25
Discovery Timeline
- 2026-06-22 - CVE-2026-54267 published to NVD
- 2026-06-22 - Last updated in NVD database
Technical Details for CVE-2026-54267
Vulnerability Analysis
Angular's hydration feature optimizes client-side bootstrap in SSR environments by serializing runtime state (such as cached HttpClient responses) into a <script> tag embedded in the HTML stream. The script tag receives a predictable identifier derived from the application ID with a -state suffix. During client bootstrap, Angular retrieves this state by calling document.getElementById('ng-state') and parses the element's textContent as JSON.
The lookup relies exclusively on an ID selector and never validates the tag type of the returned element. This allows DOM Clobbering, where an attacker injects an HTML element with id="ng-state" that appears in the DOM before the legitimate <script> tag. Browsers prioritize earlier matching elements for getElementById calls, so Angular receives the attacker-controlled element instead.
Root Cause
The root cause is missing type validation in packages/core/src/transfer_state.ts. The original code accepted any element returned by getElementById and trusted its textContent. Because Angular templates allow property bindings such as <div [id]="userInput">, untrusted input bound to the id attribute can shadow the genuine state container and feed attacker-controlled JSON into Angular's hydration pipeline.
Attack Vector
An attacker requires the ability to inject HTML attributes or elements into a rendered Angular template. This typically occurs when applications bind unsanitized CMS content or user input to element properties such as id. The injected element must render before Angular's serialized state script in the DOM tree. When hydration runs, Angular parses the attacker's payload, enabling state tampering, cache poisoning, and downstream cross-site scripting via corrupted application state.
// Locate the script tag with the JSON data transferred from the server.
// The id of the script tag is set to the Angular appId + 'state'.
const script = doc.getElementById(appId + '-state');
- if (script?.textContent) {
+ if (script?.tagName === 'SCRIPT' && script.textContent) {
try {
// Avoid using any here as it triggers lint errors in google3 (any is not allowed).
// Decoding of `<` is done of the box by browsers and node.js, same behaviour as G3
Source: Angular security commit 6bde84fa. The patch adds a tagName === 'SCRIPT' check to reject clobbered elements.
Detection Methods for CVE-2026-54267
Indicators of Compromise
- Presence of multiple DOM elements sharing the ng-state identifier within a rendered Angular page.
- Hydration-related JSON parse errors reported in browser consoles or front-end telemetry.
- CMS or user-generated content fields containing literal strings such as id="ng-state" or id="<appId>-state".
- Unexpected mutations in HttpClient cache values immediately after client bootstrap.
Detection Strategies
- Audit Angular templates for property bindings to the id attribute ([id]="...") sourced from untrusted data.
- Scan rendered SSR output for duplicate id values matching the hydration state identifier.
- Inventory deployed Angular versions and flag releases earlier than 22.0.1, 21.2.17, or 20.3.25.
- Inspect Content Security Policy (CSP) reports for blocked inline script executions tied to hydration.
Monitoring Recommendations
- Instrument client-side error reporting to capture hydration failures and JSON.parse exceptions originating in @angular/core.
- Monitor CMS publishing workflows for HTML payloads containing ng-state identifiers.
- Track outbound dependency advisories from the Angular GitHub Security Advisories feed.
How to Mitigate CVE-2026-54267
Immediate Actions Required
- Upgrade Angular to 22.0.1, 21.2.17, or 20.3.25 depending on the major version in use.
- Audit application templates for untrusted bindings to id and remove or sanitize them.
- Block CMS or user inputs that contain HTML attributes referencing ng-state identifiers.
- Validate all third-party Angular libraries for vulnerable nested dependencies.
Patch Information
The fix is committed in Angular pull request #69064 and merged in commit 6bde84fa. The patch hardens TransferState restoration by requiring the located element to have tagName === 'SCRIPT' before parsing its textContent. Full disclosure is published in GHSA-rgjc-h3x7-9mwg.
Workarounds
- Disable client hydration by removing provideClientHydration() from the application providers until upgrade is feasible.
- Strictly sanitize HTML content rendered through innerHTML or CMS pipelines to strip id attributes.
- Enforce a Content Security Policy that restricts inline script execution and limits hydration surface.
# Upgrade Angular packages to patched versions
npm install @angular/core@22.0.1 @angular/platform-server@22.0.1
# Or for the 21.x line
npm install @angular/core@21.2.17 @angular/platform-server@21.2.17
# Or for the 20.x line
npm install @angular/core@20.3.25 @angular/platform-server@20.3.25
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

