CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-88QP-P4QG-RQM6

SvelteKit Remote Functions: The Cost of Experimental Features

Alon Barad
Alon Barad
Software Engineer

Feb 19, 2026·6 min read·34 visits

Executive Summary (TL;DR)

If you enabled 'experimental.remoteFunctions' in SvelteKit < 2.52.2, your server is vulnerable to DoS. A malformed binary form payload can force the server into an expensive recursive type coercion loop.

An experimental feature in SvelteKit introduced a severe Denial of Service vulnerability via the binary form deserialization logic. By exploiting how the 'devalue' library handles object references and type coercion, an attacker can trigger massive CPU consumption.

The Hook: Shiny Toys and Hidden Traps

Developers love experimental features. It's the software equivalent of an 'Uncharted Territory' sign—irresistible. SvelteKit introduced remoteFunctions to allow seamless RPC-like calls between the client and server. To make this efficient, they needed something better than JSON. Enter devalue, a library that handles complex types like Map, Set, and cyclic references that JSON.stringify would choke on.

But here's the kicker: to support file uploads within this remote function architecture, SvelteKit implemented a custom binary deserializer for application/x-sveltekit-formdata. This deserializer reads a stream of bytes and reconstructs the form data, including file metadata. It's clever, efficient, and, as it turns out, completely trusting of the input it receives.

The vulnerability lies in how this deserializer reconstructs File objects. It assumes the metadata provided by the client (name, size, type) is well-formed. Spoiler alert: in the world of security, assuming input is well-formed is like leaving your front door unlocked because you live in a 'nice neighborhood'.

The Flaw: Type Coercion Hell

The root cause here is a classic JavaScript foot-gun: Implicit Type Coercion. When the deserialize_binary_form function processes the incoming byte stream, it encounters a definition for a File. It expects an array containing metadata: [name, type, size, lastModified, index].

The code then attempts to verify that the file data doesn't exceed the content length of the request. It does this with a simple arithmetic check:

// The code blindly trusts 'size' is a number
if (files_start_offset + file_offsets[index] + size > content_length) {
    throw deserialize_error('file data overflow');
}

See the problem? In JavaScript, the + operator and > comparison are not strictly typed. If size is not a number, the engine will try to make it a number. If an attacker provides a complex object (like a deeply nested array or a proxy to a huge BigInt) instead of a simple integer, the JavaScript engine triggers valueOf() or toString().

Because devalue allows for defining complex, recursive object graphs, an attacker can craft a payload where size references a massive, self-referential structure. The engine burns 100% CPU trying to coerce this monstrosity into a primitive number just to evaluate that if statement.

The Code: The Smoking Gun

Let's look at the diff. It's a perfect example of "we forgot to check types." The fix, introduced in version 2.52.2, essentially says: "I don't care what you think you are, you better be a number."

Here is the vulnerable logic versus the patched logic in packages/kit/src/runtime/form-utils.js:

Before (Vulnerable):

File: ([name, type, size, last_modified, index]) => {
    // Yolo. Let's do math on whatever 'size' is.
    if (files_start_offset + file_offsets[index] + size > content_length) {
        throw deserialize_error('file data overflow');
    }
    return new File(/*...*/);
}

After (Patched):

File: ([name, type, size, last_modified, index]) => {
    // The bouncer checks ID at the door.
    if (
        typeof name !== 'string' ||
        typeof type !== 'string' ||
        typeof size !== 'number' ||
        typeof last_modified !== 'number' ||
        typeof index !== 'number'
    ) {
        throw deserialize_error('invalid file metadata');
    }
 
    if (files_start_offset + file_offsets[index] + size > content_length) {
        throw deserialize_error('file data overflow');
    }
    // ...
}

The fix is boring, effectively just a block of typeof checks. But boring is safe. Boring is reliable.

The Exploit: Recursive Math of Doom

To exploit this, we don't need a buffer overflow or a ROP chain. We just need to understand devalue serialization format. We construct a payload where the size property of a file definition points to a recursive array structure.

Here is a conceptual breakdown of the attack vector:

  1. Define a Recursive Array: Create an array that contains references to itself or deeply nested children.
  2. Define a File: Create a file definition where the 3rd element (size) is a reference to that array.
  3. Send the Request: POST this to an endpoint handling remoteFunctions.

When the server parses this, it hits the size > content_length check. The engine tries to convert that recursive array to a number. It hangs.

// Conceptual PoC Payload Generator
const payload = JSON.stringify([
    // Index 0: The trap. A recursive structure.
    [...Array(100)].map(() => 0), // Base array
    // ... complex cross-references ...
    
    // The Trigger: A File object definition
    // [name, type, size (pointing to recursive structure), lastMod, index]
    ['malicious.txt', 'text/plain', ['BigInt', 1e100], 123456789, 0]
]);

The actual PoC found in the regression tests uses a mix of deep arrays and BigInt coercions to maximize the CPU spin. Since Node.js is single-threaded for the event loop, one such request effectively kills the server for everyone else.

The Impact: Why Should We Panic?

This is a Denial of Service (DoS) vulnerability. In a microservices environment, losing one node might be annoying. But for a monolithic SvelteKit application, this is fatal.

Because the exhaustion happens synchronously during the request parsing phase (before your business logic even runs), you cannot catch this with standard application-level try/catch blocks easily. The event loop locks up. Health checks fail. Kubernetes kills the pod. The pod restarts. The attacker sends another request.

It's an asymmetric attack: The attacker spends almost zero resources sending a small JSON payload, while your server spends 100% CPU trying to figure out if [Array(10000)] > 100.

The Fix: Remediation

The remediation is straightforward. If you are using @sveltejs/kit versions prior to 2.52.2, you have two options:

  1. Upgrade: Update to version 2.52.2 immediately. This includes the patch that enforces strict type checking on deserialized file metadata.
  2. Disable Experimental Features: If you cannot upgrade, check your svelte.config.js. If you have experimental: { remoteFunctions: true }, set it to false or remove it. This feature is opt-in, so if you didn't explicitly turn it on, you are safe.

Always treat experimental flags as exactly what they are: code that hasn't been battle-hardened yet.

Official Patches

SvelteOfficial patch commit

Fix Analysis (1)

Technical Appendix

CVSS Score
7.5/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
EPSS Probability
0.04%
Top 100% most exploited

Affected Systems

@sveltejs/kit

Affected Versions Detail

Product
Affected Versions
Fixed Version
@sveltejs/kit
Svelte
< 2.52.22.52.2
AttributeDetail
CWE IDCWE-400 (Uncontrolled Resource Consumption)
Attack VectorNetwork (Remote)
CVSS Score7.5 (High)
ImpactDenial of Service (CPU Exhaustion)
Exploit StatusPoC Available
Affected ComponentremoteFunctions / devalue deserializer

MITRE ATT&CK Mapping

T1499.003Endpoint Denial of Service: Application or System Exploitation
Impact
CWE-400
Uncontrolled Resource Consumption

Known Exploits & Detection

GitHubRegression test case demonstrating the DoS payload structure.

Vulnerability Timeline

Vulnerability Disclosed
2026-01-15
Patch Developed & Merged
2026-02-18
Version 2.52.2 Released
2026-02-18

References & Sources

  • [1]GitHub Advisory
  • [2]Release Notes 2.52.2

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 1 hour ago•CVE-2026-48708
7.5

CVE-2026-48708: Concurrent Template Parsing Race Condition in OliveTin leading to Cross-Request Command Contamination

CVE-2026-48708 details a critical concurrency synchronization flaw in OliveTin versions < 3000.13.0. A shared package-level text/template.Template instance is accessed concurrently across multiple goroutines without proper synchronization. When concurrent request processing occurs, a race condition causes Go runtime panics or command contamination across separate sessions, enabling denial of service or execution of contaminated commands.

Amit Schendel
Amit Schendel
1 views•6 min read
•about 2 hours ago•CVE-2026-48709
3.7

CVE-2026-48709: Missing Authorization in OliveTin ValidateArgumentType RPC Endpoint

A missing authorization vulnerability in the OliveTin system allows unauthenticated remote actors to query the ValidateArgumentType RPC endpoint. By exploiting this flaw, attackers can execute systematic brute-force and side-channel validation attacks to enumerate active action binding IDs, parameter structures, and operational metadata, bypassing configured guest authentication barriers.

Amit Schendel
Amit Schendel
2 views•7 min read
•about 13 hours ago•CVE-2026-48166
5.3

CVE-2026-48166: Timing-Based User Enumeration on Login Page in Filament

An observable timing discrepancy vulnerability (CWE-208) in Filament's administrative login page allows unauthenticated remote attackers to determine the existence of registered email addresses. This timing side-channel arises from short-circuiting logic that skips expensive password hashing checks when a queried email address is not found in the database. Attackers can execute statistical timing attacks to map active administrator accounts, facilitating subsequent targeted brute-force or credential-stuffing campaigns.

Alon Barad
Alon Barad
7 views•6 min read
•about 13 hours ago•CVE-2026-48167
6.4

CVE-2026-48167: Stored Cross-Site Scripting (XSS) via Attribute Injection in Filament ImageColumn and ImageEntry

Filament's ImageColumn (used in tables) and ImageEntry (used in infolists) components render database values inside HTML attributes without validation or sanitization. This allows an attacker to inject arbitrary HTML attributes, leading to Stored Cross-Site Scripting (XSS).

Amit Schendel
Amit Schendel
9 views•5 min read
•about 14 hours ago•CVE-2026-48480
6.6

CVE-2026-48480: Undetected Stream Truncation in netty-incubator-codec-ohttp

The Netty incubator codec for Oblivious HTTP (OHTTP) fails to verify that a cryptographically signed final chunk is received before the outer HTTP body terminates. This missing validation allows an on-path adversary to truncate chunked-OHTTP messages cleanly at a non-final chunk boundary, leading to undetected data truncation and compromising message integrity. The vulnerability affects multiple versions of the maven package io.netty.incubator:netty-incubator-codec-ohttp prior to 0.0.22.Final.

Alon Barad
Alon Barad
6 views•7 min read
•about 14 hours ago•CVE-2026-48488
2.7

CVE-2026-48488: Weak Cryptographic Hash (SHA-1) Usage for Attachment Encryption Keys in phpMyFAQ

Prior to version 4.1.4, phpMyFAQ used the cryptographically broken SHA-1 algorithm to hash custom attachment encryption keys stored in the database. Attackers with database access can recover these plaintext keys through offline brute-force attacks and subsequently decrypt sensitive file attachments.

Amit Schendel
Amit Schendel
6 views•7 min read