Aug 3, 2026·5 min read·209 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.
CVE-2026-12411 is a broken access control vulnerability in the DevLXD interface of Canonical LXD versions 6.6 through 6.8. The flaw resides in the devLXDInstancePatchHandler component, which fails to verify storage volume ownership when an instance attaches a new disk device via the /dev/lxd guest socket. When the security.devlxd.management.volumes configuration option is enabled, an untrusted guest or DevLXD identity can issue a crafted HTTP PATCH request referencing another tenant's custom storage volume. The LXD host daemon subsequently mounts the target volume into the requesting guest, permitting unauthorized cross-tenant read and write operations.
CVE-2026-105769 (GHSA-5q7h-w9jf-cx97, GO-2026-6225) is an origin validation error and credential exfiltration vulnerability affecting Kaniko prior to version 1.25.20. The flaw stems from an unanchored regular expression in the integrated Azure Container Registry (ACR) credential helper (github.com/chrismellard/docker-credential-acr-env). When Kaniko processes a Dockerfile containing an image reference hosted on a lookalike domain containing an ACR suffix as a substring (e.g., x.azurecr.io.attacker.com), the credential helper acquires a Microsoft Entra ID access token for Azure Resource Manager and transmits it via HTTP POST to the attacker-controlled host.
CVE-2026-62300 is an uncontrolled resource consumption vulnerability (CWE-400) affecting the daemon mode of filecoin-pin in versions up to and including 1.1.0. The daemon implements the IPFS Pinning Service API to store content on Filecoin's Proof of Data Possession (PDP) service. Due to the absence of rate limits, concurrency caps, execution timeouts, and Directed Acyclic Graph (DAG) traversal limits, an authenticated user—or an unauthenticated user when authentication is disabled—can exhaust system resources via crafted POST /pins requests.
CVE-2026-61536 is a high-severity Remote Code Execution (RCE) vulnerability in the masci/banks Python library prior to version 2.4.3. The flaw exists within the CompletionExtension component, which parses JSON-serialized Tool definitions directly from rendered Jinja template bodies inside {% completion %} blocks. When handling tool calls returned by an LLM, the library dynamically resolves the target callable using importlib.import_module() and getattr() based on an unvalidated import_path string. An attacker who can supply or modify prompt templates can inject a malicious Tool JSON object pointing to arbitrary Python functions (such as os.system), bypassing the Jinja SandboxedEnvironment introduced in version 2.4.2 and achieving arbitrary code execution when the LLM invokes the tool.
Payload CMS contains a missing authorization vulnerability (CWE-862) in its client-side upload instructions endpoint and the `@payloadcms/storage-vercel-blob` storage adapter. Two distinct logic defects allow authenticated users lacking collection-level `create` or `update` permissions to generate signed upload tokens and upload arbitrary files directly to external cloud storage.
CVE-2026-55098 (GHSA-93cm-2v4m-c56c) is an authorization bypass and sensitive information disclosure vulnerability in Basekick-Labs Arc prior to version 26.06.2. The flaw stems from an incomplete remediation of CVE-2026-47735, which failed to restrict the full suite of DuckDB table-valued filesystem I/O functions and quoted-identifier invocations. Because Arc's query parser ignores function calls during table reference extraction, authenticated users with minimal or empty permissions can invoke functions like parquet_scan(), glob(), and read_blob() to read, enumerate, and extract telemetry data across all tenant databases residing within the shared local storage root.