VYPR
High severity7.5NVD Advisory· Published Apr 10, 2026· Updated Apr 15, 2026

CVE-2026-40073

CVE-2026-40073

Description

SvelteKit is a framework for rapidly developing robust, performant web applications using Svelte. Prior to 2.57.1, under certain circumstances, requests could bypass the BODY_SIZE_LIMIT on SvelteKit applications running with adapter-node. This bypass does not affect body size limits at other layers of the application stack, so limits enforced in the WAF, gateway, or at the platform level are unaffected. This vulnerability is fixed in 2.57.1.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
@sveltejs/kitnpm
< 2.57.12.57.1

Affected products

1
  • cpe:2.3:a:svelte:kit:*:*:*:*:*:node.js:*:*
    Range: <2.57.1

Patches

1
3202ed6c98f9

Merge commit from fork

https://github.com/sveltejs/kitElliott JohnsonApr 9, 2026via ghsa
3 files changed · +103 5
  • .changeset/fair-chefs-strive.md+5 0 added
    @@ -0,0 +1,5 @@
    +---
    +'@sveltejs/kit': patch
    +---
    +
    +fix: enforce `BODY_SIZE_LIMIT` on chunked requests
    
  • packages/kit/src/exports/node/index.js+17 5 modified
    @@ -16,10 +16,11 @@ function get_raw_body(req, body_size_limit) {
     	}
     
     	const content_length = Number(h['content-length']);
    +	const has_content_length = Number.isFinite(content_length);
     
     	// check if no request body
     	if (
    -		(req.httpVersionMajor === 1 && isNaN(content_length) && h['transfer-encoding'] == null) ||
    +		(req.httpVersionMajor === 1 && !has_content_length && h['transfer-encoding'] == null) ||
     		content_length === 0
     	) {
     		return null;
    @@ -36,7 +37,7 @@ function get_raw_body(req, body_size_limit) {
     
     	return new ReadableStream({
     		start(controller) {
    -			if (body_size_limit !== undefined && content_length > body_size_limit) {
    +			if (body_size_limit !== undefined && has_content_length && content_length > body_size_limit) {
     				let message = `Content-length of ${content_length} exceeds limit of ${body_size_limit} bytes.`;
     
     				if (body_size_limit === 0) {
    @@ -65,11 +66,22 @@ function get_raw_body(req, body_size_limit) {
     				if (cancelled) return;
     
     				size += chunk.length;
    -				if (size > content_length) {
    +
    +				if (body_size_limit !== undefined && size > body_size_limit) {
    +					cancelled = true;
    +
    +					const message = `request body size exceeded BODY_SIZE_LIMIT of ${body_size_limit}`;
    +
    +					const error = new SvelteKitError(413, 'Payload Too Large', message);
    +					controller.error(error);
    +
    +					return;
    +				}
    +
    +				if (has_content_length && size > content_length) {
     					cancelled = true;
     
    -					const constraint = content_length ? 'content-length' : 'BODY_SIZE_LIMIT';
    -					const message = `request body size exceeded ${constraint} of ${content_length}`;
    +					const message = `request body size exceeded content-length of ${content_length}`;
     
     					const error = new SvelteKitError(413, 'Payload Too Large', message);
     					controller.error(error);
    
  • packages/kit/src/exports/node/index.spec.js+81 0 added
    @@ -0,0 +1,81 @@
    +import { PassThrough } from 'node:stream';
    +import { expect, test } from 'vitest';
    +import { getRequest } from './index.js';
    +
    +/**
    + * @param {{
    + * 	headers?: Record<string, string>;
    + * 	bodySizeLimit?: number;
    + * }} [options]
    + */
    +async function create_request(options = {}) {
    +	const req = new PassThrough();
    +	const incoming = /** @type {import('http').IncomingMessage} */ (/** @type {unknown} */ (req));
    +
    +	incoming.headers = {
    +		'content-type': 'text/plain',
    +		...options.headers
    +	};
    +	incoming.method = 'POST';
    +	incoming.url = '/';
    +	incoming.httpVersionMajor = 1;
    +
    +	return {
    +		request: await getRequest({
    +			request: incoming,
    +			base: 'http://localhost',
    +			bodySizeLimit: options.bodySizeLimit
    +		}),
    +		req
    +	};
    +}
    +
    +test('rejects chunked request bodies that exceed body size limit', async () => {
    +	const { request, req } = await create_request({
    +		headers: { 'transfer-encoding': 'chunked' },
    +		bodySizeLimit: 10
    +	});
    +
    +	const text = request.text();
    +
    +	req.write(Buffer.from('0123456789'));
    +	req.write(Buffer.from('x'));
    +	req.end();
    +
    +	await expect(text).rejects.toMatchObject({
    +		status: 413,
    +		text: 'Payload Too Large',
    +		message: 'request body size exceeded BODY_SIZE_LIMIT of 10'
    +	});
    +});
    +
    +test('allows chunked request bodies within body size limit', async () => {
    +	const { request, req } = await create_request({
    +		headers: { 'transfer-encoding': 'chunked' },
    +		bodySizeLimit: 10
    +	});
    +
    +	const text = request.text();
    +
    +	req.write(Buffer.from('0123456789'));
    +	req.end();
    +
    +	await expect(text).resolves.toBe('0123456789');
    +});
    +
    +test('rejects request bodies that exceed content-length', async () => {
    +	const { request, req } = await create_request({
    +		headers: { 'content-length': '4' }
    +	});
    +
    +	const text = request.text();
    +
    +	req.write(Buffer.from('01234'));
    +	req.end();
    +
    +	await expect(text).rejects.toMatchObject({
    +		status: 413,
    +		text: 'Payload Too Large',
    +		message: 'request body size exceeded content-length of 4'
    +	});
    +});
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.