Feb 28, 2026·7 min read·1 visit
SvelteKit versions prior to the fix contain a Denial of Service vulnerability in the experimental `deserialize_binary_form` function. Attackers can map thousands of file objects to a single byte range, causing logical amplification and resource exhaustion.
A resource exhaustion vulnerability exists in SvelteKit's experimental binary form handling mechanism. The deserialization logic for remote functions fails to validate that file metadata entries correspond to unique, non-overlapping byte ranges in the request body. This allows an attacker to craft a small HTTP request that expands into a massive logical payload when processed, consuming excessive server memory and CPU cycles.
SvelteKit, a framework for building web applications with Svelte, includes an experimental feature for handling complex form submissions and remote functions (actions) using a custom binary serialization format. This format is designed to efficiently transmit data types that JSON cannot handle natively, such as Date, Map, Set, and binary File objects.
The vulnerability, identified as GHSA-fpg4-jhqr-589c, resides in the deserialize_binary_form function within the runtime package. This function parses incoming requests with the application/x-sveltekit-binary-form content type. The parser reconstructs the payload by reading a header, a metadata block (encoded using the devalue library), an offset table, and the raw binary body.
The flaw involves a logical expansion issue where the parser trusts the metadata definitions without verifying the physical layout of the binary data. Specifically, the implementation allows multiple File objects defined in the metadata to reference the same byte range in the request body. This permits an "amplification" attack where a small network payload is expanded into a large number of in-memory objects or processing operations, leading to Denial of Service (DoS).
The root cause is a lack of structural validation in the deserialize_binary_form function located in packages/kit/src/runtime/form-utils.js. The binary format separates the logical definition of data from the physical bytes.
The request body is structured as follows:
devalue), containing placeholders for files.When the parser encounters a File in the metadata, it uses an index to look up the corresponding start and end positions in the offset table. It then creates a LazyFile object backed by that slice of the request body.
Prior to the patch, the code did not enforce a one-to-one mapping between metadata entries and physical bytes. An attacker could define an array of 10,000 files in the metadata, all pointing to index 0 in the offset table. If index 0 points to a 1MB block of dummy data, the server logically instantiates 10,000 file objects, each 1MB in size. While the physical memory usage might be deduplicated depending on the specific buffer implementation, any application logic that iterates over these files (e.g., calculating checksums, writing to disk, or validating content) will process 10GB of data from a single 1MB request.
The remediation involves strict validation to ensure the binary payload is well-formed and non-overlapping. The patch was applied in commit faba869db3644077169bf5d7c6e41fd5f3d6c65e.
The previous implementation simply looked up the offset and created the file, allowing reuse:
// Pseudo-code of vulnerable logic
const files = metadata.map(entry => {
const [start, end] = offset_table[entry.index];
return new File(body.slice(start, end), entry.name);
});The fix introduces a rigorous validation step that enforces "contiguous and non-overlapping" file spans. It ensures that every byte in the data section belongs to exactly one file.
// patched version in packages/kit/src/runtime/form-utils.js
// 1. Collect all spans (start, end) from the offset table
const spans = [];
// ... loop to populate spans ...
// 2. Sort spans by start offset
spans.sort((a, b) => a.start - b.start);
// 3. Validate continuity
let expected_start = 0;
for (const span of spans) {
// CHECK: Gap detection
if (span.start !== expected_start) {
throw new Error('Invalid binary form data (gap)');
}
// CHECK: Overlap detection (implicit via sorting and end check)
expected_start = span.end;
}
// 4. Validate total length
if (expected_start !== total_data_length) {
throw new Error('Invalid binary form data (trailing data)');
}> [!NOTE] > The patch also ensures that each index in the offset table is used exactly once, preventing multiple metadata entries from referencing the same offset definition.
To exploit this vulnerability, an attacker acts as a client interacting with a SvelteKit application endpoint that utilizes experimental actions or remote functions accepting binary forms. No authentication is strictly required unless the specific endpoint is protected.
The attacker constructs a POST request with Content-Type: application/x-sveltekit-binary-form. The body is crafted manually to bypass standard client-side serialization.
devalue payload containing an array of thousands of File objects. All of these objects reference the same index (e.g., 0) in the offset table.0 that covers the entire data segment (e.g., 100 KB).When the server receives this request:
File objects.formData.values() (a common pattern for file uploads), it processes the 100 KB block thousands of times.The primary impact of this vulnerability is Denial of Service (DoS). By exhausting server resources, an attacker can render the application unresponsive.
CVSS v3.1 Calculation:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:HThis issue is specific to the Node.js runtime of SvelteKit where this binary handling is implemented; it may not affect adapter-specific deployments that handle bodies differently, though the core logic is in the framework itself.
The vulnerability is patched in the @sveltejs/kit package. Users should upgrade immediately to the latest version available on the 2.x branch.
Upgrade @sveltejs/kit to the latest version (e.g., 2.5.3 or newer). The fix is contained in commit faba869db3644077169bf5d7c6e41fd5f3d6c65e. Verify the installation:
npm ls @sveltejs/kitIf an immediate upgrade is not feasible, the following mitigations can reduce risk:
Content-Type: application/x-sveltekit-binary-form. This effectively neutralizes the attack vector but will break legitimate functionality relying on this specific binary serialization.CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
@sveltejs/kit Svelte | < 2.x (patched version) | See Release Notes |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-770 |
| Attack Vector | Network |
| CVSS Score | 7.5 (High) |
| Impact | Denial of Service |
| Exploit Status | Proof of Concept Available |
| Platform | Node.js / SvelteKit |
Allocation of Resources Without Limits or Throttling