Aug 3, 2026·5 min read·172 visits
Improper query parameter serialization in Angular's HttpTransferCache yields identical cache keys for semantically different requests, allowing remote attackers to poison application states during SSR hydration.
An in-depth technical analysis of CVE-2026-68945, a high-severity security vulnerability in Angular's `@angular/common/http` package. The flaw stems from an ambiguity in how query parameters are serialized to generate cache keys during Server-Side Rendering (SSR) within the `HttpTransferCache` component. By failing to encode delimiters and implicitly coercing arrays to comma-joined strings, the serialization mechanism yields identical cache keys for distinct requests, facilitating State Poisoning and Cross-Request Response Reuse.
Angular applications employing Server-Side Rendering (SSR) often utilize the HttpTransferCache component inside the @angular/common/http package. This component serves as a performance optimization. When rendering a page on the server, the application serializes HTTP request-response pairs and embeds them in the HTML document. This metadata is transferred to the client, preventing duplicate HTTP requests during browser-side application hydration.
To identify and retrieve cached responses, the client-side hydration engine generates a deterministic cache key for each outgoing request. This key must uniquely represent the requested endpoint, including all associated query parameters. If the system generates the same cache key for two semantically distinct HTTP requests, the cache-key collision causes the client to reuse incorrect server-rendered data.
CVE-2026-68945 defines a critical flaw in this key-generation logic. The implementation in @angular/common/http allowed an unauthenticated remote attacker to generate colliding cache keys by structuring query parameters with specific delimiters or comma-separated arrays. This design flaw leads directly to Cross-Request Response Reuse and client-side State Poisoning.
The root cause of this vulnerability lies in the manual string serialization logic located within sortAndConcatParams in packages/common/http/src/transfer_cache.ts. Prior to the patch, the function mapped over the query parameter keys, sorted them, and converted key-value pairs into a string using the following logic:
${k}=${params.getAll(k)}
This implementation introduced two fundamental vulnerabilities. First, the logic relied on implicit array-to-string coercion. In JavaScript and TypeScript, interpolating an array (returned by params.getAll(k)) into a template string implicitly invokes Array.prototype.toString(). This joins the array elements with commas without escaping individual values. For example, a single scalar parameter containing a comma (?role=user,admin) produces the serialized output role=user,admin. Concurrently, a repeated parameter containing distinct values (?role=user&role=admin) returns ['user', 'admin'] from getAll, which also coerces to the identical output role=user,admin.
Second, the serialization logic failed to URL-encode the keys and values. Because ampersands (&) and equals signs (=) were not percent-encoded, an attacker could perform delimiter injection. A parameter key-value pair of a=1&b=2 would generate the serialized string fragment a=1&b=2. This output matches the serialization of a legitimate request with two discrete query parameters: a=1 and b=2.
The original, vulnerable implementation of the serialization helper function, along with the corrected logic introduced in the patch, highlights the shift from custom serialization to native standard APIs.
// VULNERABLE CODE PATH
function sortAndConcatParams(params: HttpParams | URLSearchParams): string {
return [...params.keys()]
.sort()
// params.getAll(k) returns string[], coerced via toString() to comma-separated values
.map((k) => `${k}=${params.getAll(k)}`)
.join('&');
}In the vulnerable scenario, sortAndConcatParams does not utilize safety utilities to sanitise characters like ,, &, or =. This allows structural manipulation of the serialized key structure.
// PATCHED CODE PATH
function sortAndConcatParams(params: HttpParams | URLSearchParams): string {
const searchParams = new URLSearchParams(
params instanceof URLSearchParams ? params : params.toString(),
);
searchParams.sort();
return searchParams.toString();
}The patch replaces the custom concatenation loop entirely. By instantiating a platform-native URLSearchParams object and sorting it via the native sort() method, Angular ensures that query parameter delimiters are correctly processed. The standard toString() method of URLSearchParams applies percent-encoding to commas, ampersands, and equal signs. Consequently, ?role=user,admin correctly serializes to role=user%2Cadmin, whereas ?role=user&role=admin serializes to role=user&role=admin, eliminating the key ambiguity.
Exploiting this flaw requires an Angular application that dynamically loads data during SSR based on query parameter input. An attacker targets the SSR engine to populate the cache with a crafted payload, which a victim subsequently retrieves via a normal application flow.
An attacker initiates a request to the application using a comma-separated format designed to mimic a multi-parameter administrative state. The SSR server processes the request and places a low-privilege or spoofed response in the cache with the serialized key role=user,admin. When a legitimate user loads the application using repeated parameters, the client-side hydration engine computes the cache key, gets a hit on the colliding entry, and hydrates the application with the attacker's cached state rather than performing a fresh backend API query.
The impact of CVE-2026-68945 is categorized as client-side State Poisoning and Cross-Request Response Reuse. If an application uses query parameters to determine authorization states, user contexts, or display content during SSR, this vulnerability can lead to security bypasses. An attacker can seed the server-side cache with unauthorized content that is subsequently presented to legitimate users.
In scenarios where the client relies on hydrated server responses to set user access levels or transaction details, the application's integrity is compromised. Because exploitation requires no authentication and can be performed remotely via standard network channels, the threat complexity is low. While it does not enable arbitrary server-side code execution, the high confidentiality impact and risk of data manipulation warrant the assigned CVSS score of 8.8.
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
@angular/common Angular | < 20.3.27 | 20.3.27 |
@angular/common Angular | >= 21.0.0-next.0, < 21.2.19 | 21.2.19 |
@angular/common Angular | >= 22.0.0-next.0, < 22.0.2 | 22.0.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-345 |
| Attack Vector | Network |
| CVSS Score | 8.8 |
| Exploit Status | Proof-of-Concept |
| Impact | State Poisoning / Cross-Request Response Reuse |
| KEV Status | Not Listed |
The application does not sufficiently verify that the received data matches the semantic intent of the client-side request.
A security feature bypass vulnerability in the Falco k8saudit plugin (and its cloud-specific variants) allowed privileged workloads to run undetected. This bypass occurred because the plugin's default extraction logic and rules only evaluated standard containers, completely omitting initContainers and ephemeralContainers.
nginx-ignition is a web-based user interface for managing the Nginx web server. In versions 2.33.0 through 2.35.0, the application is vulnerable to an improper authentication flaw (CWE-287) in its Multi-Factor Authentication (MFA) implementation. The stateless validation of Time-Based One-Time Passwords (TOTP) allows an attacker to reuse a captured, active verification code multiple times within the standard 30-second validity window, successfully bypassing secondary authentication checks if primary credentials are known.
A vulnerability exists in the i18n middleware of nginx-ignition, enabling CPU amplification attacks. By transmitting a crafted Accept-Language header containing malformed tags separated by underscores, an unauthenticated remote attacker can bypass the length-guard threshold of the underlying Go parsing library. Normalization of underscores to hyphens occurs after the initial validation checks, forcing the parser into expensive quadratic-time loops that consume 100% of available CPU resources. This leads to a complete denial of service for the administrative API and potentially degrades the availability of the hosting system. This vulnerability has been resolved in version 2.40.1.
Nginx Ignition prior to version 2.41.1 contains a Time-of-Check to Time-of-Use (TOCTOU) race condition in its unauthenticated onboarding API endpoint. This flaw allows remote, unauthenticated attackers to register an administrative account by sending concurrent HTTP requests during the initial system configuration phase, bypassing the check meant to restrict onboarding to a single initial administrator.
A logic error in Hatchet's OAuth state validation mechanism allows unauthenticated remote attackers to bypass state parameter verification. By submitting an empty state parameter, attackers can exploit an equality collision with cleared session keys, facilitating Login Cross-Site Request Forgery (Login CSRF) or Session Fixation.
A high-severity access control vulnerability in ToolHive CLI before v0.30.1 and ToolHive Studio before v0.38.0 allows local containerized MCP servers to bypass network isolation. This enables malicious workloads to establish TCP/IP connections to administrative and control plane endpoints exposed on the host loopback interface.