highCVE-2026-68945Aug 3, 2026

CVE-2026-68945: @angular/common HttpTransferCache Cache-Key Ambiguity Leads to State Poisoning

Rohit Hatagale
AI Security Researcher, SecureLayer7

Angular's server-side rendering cache treats two structurally different HTTP requests as identical, letting an attacker-controlled response be silently served in place of a legitimate one during…

Package@angular/common
Ecosystemnpm
Affected>= 22.0.0-next.0, < 22.0.2
Fixed in22.0.2
CVE-2026-68945: @angular/common HttpTransferCache Cache-Key Ambiguity Leads to State Poisoning

The problem

Angular's HttpTransferCache stores SSR responses so the browser can reuse them during hydration instead of re-fetching. When building the cache key, repeated multi-value parameters were joined with commas, the same character a scalar string value can contain.

This means role=user,admin (one param, one string value) and role=user&role=admin (one param, two values) produced the same key material. Any two requests that share a URL but differ only in how they pass a repeated parameter were treated as the same request, so whichever ran first wins and the second never reaches the backend.

Proof of concept

A working proof-of-concept for CVE-2026-68945 in @angular/common, with the exact payload below.

javascript
// Two distinct Angular HttpClient calls that collide to the same transfer-cache key
// Call 1 - scalar comma value (attacker-influenced, runs first during SSR)
this.http.get('/api/resource', {
  params: new HttpParams().set('role', 'user,admin')
});

// Call 2 - trusted multi-value request (runs second, hits the poisoned cache entry)
this.http.get('/api/resource', {
  params: new HttpParams().append('role', 'user').append('role', 'admin')
});

// Both serialise to the key material: role=user,admin
// Call 2 never reaches the backend; it receives Call 1's cached response.

The bug lives in the cache-key construction step inside HttpTransferCache. Before the fix, multi-value params were collapsed with .join(','), so ['user','admin'] became the string user,admin, which is byte-identical to the scalar value user,admin. The patch changes how repeated keys are serialised into the key string so that role=user&role=admin and role=user,admin produce distinct key material, making the ambiguity structurally impossible.

CWE-345 (Insufficient Verification of Data Authenticity) applies because the cache never verified that a stored entry actually corresponded to the semantics of the incoming request.

The fix

Upgrade to @angular/common 22.0.2 (or 21.2.19 / 20.3.27 for older trains). If an immediate upgrade is not possible, set transferCache: false on any sensitive request, or disable the transfer cache globally with provideClientHydration(withNoHttpTransferCache()).

Reporter not attributed.

References: [1][2][3][4][5][6]

Related research