@angular/common: Information Leak via Default Caching of Credentialed Requests in HttpTransferCache
Description
Angular HttpTransferCache in SSR-enabled apps caches credentialed requests by default, allowing cached HTML to leak user-specific data via shared caches.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Angular HttpTransferCache in SSR-enabled apps caches credentialed requests by default, allowing cached HTML to leak user-specific data via shared caches.
Vulnerability
In @angular/common, the HttpTransferCache utility caches outgoing HTTP requests during Server-Side Rendering (SSR) and transfers them to the client via TransferState. However, it does not inspect the withCredentials flag or the Cookie header of outgoing requests [1]. As a result, credentialed, user-specific responses are cached by default in the shared TransferState payload, which is serialized into the SSR-rendered HTML [3]. Affected versions include >=22.0.0-next.0, <22.0.0-rc.2; >=21.0.0-next.0, <21.2.15; >=20.0.0-next.0, <20.3.22; >=19.0.0-next.0, <19.2.23; and <=18.2.14 [1].
Exploitation
An attacker with access to a shared cache (e.g., CDN, reverse proxy) that caches the SSR-rendered HTML pages can exploit this vulnerability [3]. When an authenticated user makes a request that triggers SSR, the user's private data (e.g., from API responses) is included in the cached HTML. Subsequent unauthenticated requests to the same URL receive the cached HTML containing the first user's sensitive information [1]. No additional user interaction is required beyond normal application usage.
Impact
Successful exploitation leads to information disclosure of user-specific data to unauthorized users [1]. The attacker gains access to sensitive information such as personal details, authentication tokens, or other confidential data present in the cached HTTP responses. This is a high-severity vulnerability (CVSS high) [1].
Mitigation
Angular has released patches in versions 22.0.0-rc.2, 21.2.15, 20.3.22, and 19.2.23 [1]. The fix, introduced in PR #67964 [2], modifies the default behavior to skip caching requests that include a Cookie header or use withCredentials: true. Users should upgrade their @angular/common package to one of the patched versions immediately. As a workaround, if upgrading is not possible, ensure that caching layers (CDN, reverse proxy) are configured to not cache HTML pages containing authenticated content (e.g., using Vary: Cookie or Cache-Control: private headers) [3].
AI Insight generated on Jun 15, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
1Patches
134090cb12ec2fix(http): exclude withCredentials requests from transfer cache
3 files changed · +26 −3
adev/src/content/guide/ssr.md+2 −2 modified@@ -432,7 +432,7 @@ To configure this, update your `angular.json` file as follows: You can customize how Angular caches HTTP responses during server‑side rendering (SSR) and reuses them during hydration by configuring `HttpTransferCacheOptions`. This configuration is provided globally using `withHttpTransferCacheOptions` inside `provideClientHydration()`. -By default, `HttpClient` caches all `HEAD` and `GET` requests which don't contain `Authorization`, `Proxy-Authorization`, or `Cookie` headers. You can override those settings by using `withHttpTransferCacheOptions` to the hydration configuration. +By default, `HttpClient` caches all `HEAD` and `GET` requests which don't contain `Authorization`, `Proxy-Authorization`, or `Cookie` headers and are not sent with `withCredentials`. You can override those settings by using `withHttpTransferCacheOptions` to the hydration configuration. ```ts import {bootstrapApplication} from '@angular/platform-browser'; @@ -487,7 +487,7 @@ Use this only when `POST` requests are **idempotent** and safe to reuse between ### `includeRequestsWithAuthHeaders` Determines whether requests containing `Authorization`, `Proxy‑Authorization`, or `Cookie` headers are eligible for caching. -By default, these are excluded to prevent caching user‑specific responses. +By default, these are excluded to prevent caching user‑specific responses. Requests sent with `withCredentials` are also excluded by default. ```ts withHttpTransferCacheOptions({
packages/common/http/src/transfer_cache.ts+3 −1 modified@@ -42,7 +42,7 @@ import {HttpParams} from './params'; * (for example using GraphQL). * @param includeRequestsWithAuthHeaders Enables caching of requests containing `Authorization`, * `Proxy-Authorization`, or `Cookie` headers. By default, these requests are excluded from - * caching. + * caching. Requests sent using `withCredentials` are also excluded by default. * * @see [Configuring the caching options](guide/ssr#configuring-the-caching-options) * @@ -131,6 +131,8 @@ function shouldCacheRequest(req: HttpRequest<unknown>, options: CacheOptions): b if ( !isCacheActive || requestOptions === false || + // Do not cache requests sent with credentials. + req.withCredentials || // POST requests are allowed either globally or at request level (requestMethod === 'POST' && !globalOptions.includePostRequests && !requestOptions) || (requestMethod !== 'POST' && !ALLOWED_METHODS.includes(requestMethod)) ||
packages/common/http/test/transfer_cache_spec.ts+21 −0 modified@@ -40,6 +40,7 @@ interface RequestParams { observe?: 'body' | 'response'; transferCache?: {includeHeaders: string[]} | boolean; headers?: {[key: string]: string}; + withCredentials?: boolean; body?: RequestBody; } @@ -429,6 +430,16 @@ describe('TransferCache', () => { makeRequestAndExpectOne('/test-auth', 'foo'); }); + it('should not cache requests with credentials', async () => { + makeRequestAndExpectOne('/test-auth', 'foo', { + withCredentials: true, + }); + + makeRequestAndExpectOne('/test-auth', 'foo', { + withCredentials: true, + }); + }); + it('should cache POST with the differing body in string form', () => { makeRequestAndExpectOne('/test-1', null, {method: 'POST', transferCache: true, body: 'foo'}); makeRequestAndExpectNone('/test-1', 'POST', {transferCache: true, body: 'foo'}); @@ -581,6 +592,16 @@ describe('TransferCache', () => { makeRequestAndExpectNone('/test-auth'); }); + it(`should not cache requests with credentials when 'includeRequestsWithAuthHeaders' is 'true'`, async () => { + makeRequestAndExpectOne('/test-auth', 'foo', { + withCredentials: true, + }); + + makeRequestAndExpectOne('/test-auth', 'foo', { + withCredentials: true, + }); + }); + it('should cache a POST request', () => { makeRequestAndExpectOne('/include?foo=1', 'post-body', {method: 'POST'});
Vulnerability mechanics
Root cause
"The `HttpTransferCache` caching mechanism fails to inspect the `withCredentials` flag or `Cookie` header of outgoing requests, causing credentialed, user-specific responses to be cached by default in the shared `TransferState` payload. [patch_id=6084660]"
Attack vector
An unauthenticated attacker can obtain another user's private data by requesting a cached SSR-rendered HTML page that was previously generated for an authenticated user. The `HttpTransferCache` in `@angular/common` did not inspect the `withCredentials` flag or `Cookie` header of outgoing requests, so credentialed, user-specific responses were cached by default in the shared `TransferState` payload [patch_id=6084660]. When that payload is serialized into the HTML and stored by a shared caching layer (CDN, reverse proxy, or server cache), subsequent requests for the same page receive the cached HTML containing the first user's private data. The preconditions are that SSR and hydration are enabled, the application performs credentialed HTTP requests during SSR, and the HTML responses are cached by a shared cache without proper cache-control headers.
What the fix does
The patch adds a `req.withCredentials` check inside the `shouldCacheRequest` function in `packages/common/http/src/transfer_cache.ts`, so any request sent with the `withCredentials` flag is unconditionally excluded from the transfer cache [patch_id=6084660]. Previously, only requests with explicit `Authorization`, `Proxy-Authorization`, or `Cookie` headers were excluded, but requests could carry credentials via the `withCredentials` flag without those headers. The documentation in `adev/src/content/guide/ssr.md` is also updated to reflect that `withCredentials` requests are excluded by default, and the `includeRequestsWithAuthHeaders` option no longer overrides this exclusion.
Preconditions
- configSSR and hydration must be enabled (e.g., using `provideClientHydration()`).
- inputThe application must perform HTTP requests that require user-specific authentication (cookies or `withCredentials: true`) during SSR.
- configThe SSR-rendered HTML must be cached by a shared caching layer (CDN, reverse proxy, or server cache) without proper cache-control headers.
Generated on Jun 15, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
3News mentions
0No linked articles in our index yet.