May 21, 2026·7 min read·1 visit
A state isolation failure in SvelteKit's query.batch allows concurrent remote requests to intermingle, exposing sensitive session data across users. Upgrading to version 2.60.1 implements AsyncLocalStorage to properly isolate request contexts and mitigate the vulnerability.
The SvelteKit framework contains a critical cross-talk vulnerability within its server-side rendering (SSR) processing logic. The query.batch functionality improperly scopes state variables during concurrent request handling, allowing data intended for one user session to be exposed to another. The issue is resolved in version 2.60.1 by migrating the batching state to a strictly isolated request store.
The @sveltejs/kit framework contains a critical cross-talk vulnerability within its server-side rendering (SSR) processing logic. This flaw specifically affects the query.batch functionality used for remote function calls and batched data fetching. Applications utilizing versions prior to 2.60.1 expose sensitive session data to concurrent users connecting to the affected endpoints.
The vulnerability manifests as an Exposure of Data Element to Wrong Session (CWE-488) and Exposure of Sensitive Information to an Unauthorized Actor (CWE-200). The framework incorrectly scopes state management variables during the batched execution of SSR requests. This allows data originating from one user request to intermingle with data from a completely separate, concurrent request.
The core issue resides in the Node.js execution environment, where asynchronous operations share the same memory space. Because the framework fails to isolate the request state properly, requests landing in the same macrotask share the batched data pool. An attacker exploits this behavior by sending synchronized requests to capture responses intended for legitimate users.
The root cause of GHSA-HGV7-V322-MMGR lies in the improper management of state variables within the batch function located at packages/kit/src/runtime/app/server/remote/query.js. The framework implements a batching mechanism to combine multiple data-fetching operations into a single execution step. This optimizes server performance by reducing redundant database or API calls during complex server-side rendering operations.
In vulnerable versions, the function initializes a standard JavaScript Map to track these batched operations. This Map object is scoped locally to the batch function module rather than being bound to the lifecycle of an individual HTTP request. Because Node.js handles multiple concurrent requests asynchronously within a single event loop thread, this local variable effectively becomes global shared state across all active requests.
When the server receives multiple requests simultaneously, the batch function pushes the respective queries into the same shared Map. A setTimeout operation then schedules the processing of these collected queries in a subsequent event loop iteration. Node.js executes this timeout macrotask, processing all accumulated entries regardless of their originating request context.
Once the timeout fires, the function resolves all accumulated entries and distributes the combined results back to the waiting resolvers. The framework logic fails to validate the origin of the request data against the destination resolver. Consequently, the server dispatches the mixed payloads across the active HTTP connections indiscriminately.
The vulnerable implementation relies on a shared batching variable that persists across different asynchronous request executions. The framework defines let batching = new Map(); outside the immediate request handling logic, allowing multiple concurrent HTTP handlers to append their specific payloads to this single object. The lack of isolation causes the resolver to return aggregated data to all participating connections.
// Vulnerable Implementation (Simplified)
function batch(validate_or_fn, maybe_fn) {
// Shared state across concurrent requests
let batching = new Map();
return (payload) => {
return new Promise((resolve, reject) => {
const entry = batching.get(payload);
// ... payload appended to the shared batching map ...
setTimeout(async () => {
const batched = batching;
batching = new Map(); // Reset for next batch
// Processes entries and resolves to mixed connections
}, 0);
});
};
}The SvelteKit maintainers addressed this flaw in commit dadaefc2e647a0a62f49f3ee8bc7aa46f5e27056 by introducing strict request isolation. The patch removes the shared batching variable entirely. Instead, it utilizes get_request_store(), an internal function that wraps Node.js AsyncLocalStorage, to retrieve the current request state.
// Patched Implementation (Simplified)
function batch(validate_or_fn, maybe_fn) {
const validate = create_validator(validate_or_fn, maybe_fn);
// The global map is removed
return (payload) => {
// Retrieves state specifically bound to the current async execution context
const { event, state } = get_request_store();
return new Promise((resolve, reject) => {
// State is now isolated per request
const batches = (state.remote.batches ??= new Map());
let batched = batches.get(__.id);
});
};
}By attaching the batches Map directly to the state.remote.batches property, the framework guarantees that each batched operation pool belongs exclusively to the originating HTTP request. AsyncLocalStorage ensures that asynchronous execution contexts maintain rigid memory boundaries. This structural change systematically eliminates the cross-talk vulnerability.
Exploitation of GHSA-HGV7-V322-MMGR requires the target application to utilize the query.batch feature for processing remote function calls. The attacker must possess network access to the application endpoints that trigger these batched queries. No prior authentication is necessary to trigger the race condition itself, though accessing specific batched endpoints may require valid session tokens depending on the application architecture.
The attacker executes the exploit by generating a high volume of concurrent HTTP requests targeting the vulnerable batched endpoint. The objective is to ensure the attacker's requests land in the same Node.js macrotask as a legitimate user's request. When the timing aligns correctly, the SvelteKit server aggregates both the attacker's and the victim's query payloads into the single shared Map.
Once the server processes the batched queries, it iterates through the accumulated resolvers and distributes the results. Because the payloads reside mixed in shared memory, the server inadvertently transmits the victim's data payload back over the attacker's HTTP connection. The attacker then parses the response body to extract sensitive information originally intended for the legitimate user.
This vulnerability introduces severe confidentiality risks by enabling the leakage of sensitive session data between unrelated users. The exact nature of the exposed information depends entirely on the specific data handled by the query.batch functionality within the target application. Potential leaks include authentication tokens, personally identifiable information (PII), financial records, or proprietary business logic parameters.
The estimated CVSS v3.1 base score for this vulnerability ranges from 8.1 to 9.1, reflecting a High to Critical severity level. The attack vector is strictly remote, and the exploitation requires low complexity without any special privileges. The vulnerability directly breaks the fundamental isolation expected in web application session management.
While the vulnerability primarily impacts data confidentiality and integrity (due to session mixing), it does not natively grant remote code execution or arbitrary file read capabilities. The underlying server infrastructure remains fully isolated. However, the exposure of session tokens or administrative data enables secondary attacks that facilitate complete application compromise.
The primary and most effective remediation strategy is upgrading the @sveltejs/kit package to version 2.60.1 or later. This release contains the finalized patch implementing AsyncLocalStorage for request state isolation. Development teams must update their package.json dependencies, regenerate lockfiles, and redeploy the affected applications to production environments.
For organizations unable to immediately patch, security teams must implement interim mitigations by auditing the application codebase for any usage of query.batch. Disabling the batching feature entirely eliminates the vulnerable code path. Teams must temporarily replace batched remote function calls with individual, non-batched queries until the underlying framework update is feasible.
> [!NOTE] > Standard Web Application Firewalls (WAFs) cannot reliably detect or block this attack. The concurrent requests used to exploit the race condition appear identical to legitimate application traffic. Remediation must occur directly at the application code level.
Post-remediation activities require a thorough review of application access logs during the vulnerable period. Security analysts should search for anomalous spikes in concurrent requests targeting batched query endpoints. Organizations handling highly sensitive data must consider enforcing global session invalidations to mitigate the risk of compromised authentication tokens.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
@sveltejs/kit Svelte | < 2.60.1 | 2.60.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-488 (Exposure of Data Element to Wrong Session) |
| Attack Vector | Network |
| CVSS Score | 8.1 - 9.1 (Estimated) |
| Impact | Sensitive Information Disclosure / Session Cross-Talk |
| Exploit Status | No public weaponized exploits; theoretical race condition |
| Affected Component | query.batch in SvelteKit SSR |
An application fails to properly separate session contexts, allowing data or control information intended for one session to bleed into another.