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

CVE-2026-40074

CVE-2026-40074

Description

SvelteKit is a framework for rapidly developing robust, performant web applications using Svelte. Prior to 2.57.1, redirect, when called from inside the handle server hook with a location parameter containing characters that are invalid in a HTTP header, will cause an unhandled TypeError. This could result in DoS on some platforms, especially if the location passed to redirect contains unsanitized user input. 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
10d7b44425c3

Merge commit from fork

https://github.com/sveltejs/kitElliott JohnsonApr 9, 2026via ghsa
8 files changed · +70 11
  • .changeset/brown-eggs-lose.md+5 0 added
    @@ -0,0 +1,5 @@
    +---
    +'@sveltejs/kit': patch
    +---
    +
    +fix: better validation for `redirect` inputs
    
  • packages/kit/src/exports/index.js+1 1 modified
    @@ -106,7 +106,7 @@ export function isHttpError(e, status) {
      * @param {300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number)} status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). Must be in the range 300-308.
      * @param {string | URL} location The location to redirect to.
      * @throws {Redirect} This error instructs SvelteKit to redirect to the specified location.
    - * @throws {Error} If the provided status is invalid.
    + * @throws {Error} If the provided status is invalid or the location cannot be used as a header value.
      * @return {never}
      */
     export function redirect(status, location) {
    
  • packages/kit/src/exports/index.spec.js+24 1 modified
    @@ -1,4 +1,4 @@
    -import { normalizeUrl } from './index.js';
    +import { isRedirect, normalizeUrl, redirect } from './index.js';
     import { assert, describe, it } from 'vitest';
     
     describe('normalizeUrl', () => {
    @@ -51,3 +51,26 @@ describe('normalizeUrl', () => {
     		assert.equal(denormalize('/baz').href, 'http://example.com/baz/__route.js');
     	});
     });
    +
    +describe('redirect', () => {
    +	it('throws Redirect for valid locations', () => {
    +		try {
    +			redirect(307, '/valid-location');
    +			assert.fail('Expected redirect to throw');
    +		} catch (e) {
    +			if (!isRedirect(e)) {
    +				assert.fail('Expected a Redirect error');
    +			}
    +
    +			assert.equal(e.status, 307);
    +			assert.equal(e.location, '/valid-location');
    +		}
    +	});
    +
    +	it('throws a descriptive error for invalid redirect locations', () => {
    +		assert.throws(
    +			() => redirect(307, '/invalid\r\nset-cookie: x=y'),
    +			'Invalid redirect location "/invalid\\r\\nset-cookie: x=y": this string contains characters that cannot be used in HTTP headers'
    +		);
    +	});
    +});
    
  • packages/kit/src/exports/internal/index.js+9 0 modified
    @@ -27,6 +27,15 @@ export class Redirect {
     	 * @param {string} location
     	 */
     	constructor(status, location) {
    +		try {
    +			new Headers({ location });
    +		} catch {
    +			throw new Error(
    +				`Invalid redirect location ${JSON.stringify(location)}: ` +
    +					'this string contains characters that cannot be used in HTTP headers'
    +			);
    +		}
    +
     		this.status = status;
     		this.location = location;
     	}
    
  • packages/kit/src/runtime/server/respond.js+12 8 modified
    @@ -525,14 +525,18 @@ export async function internal_respond(request, options, manifest, state) {
     		return response;
     	} catch (e) {
     		if (e instanceof Redirect) {
    -			const response =
    -				is_data_request || remote_id
    -					? redirect_json_response(e)
    -					: route?.page && is_action_json_request(event)
    -						? action_json_redirect(e)
    -						: redirect_response(e.status, e.location);
    -			add_cookies_to_headers(response.headers, new_cookies.values());
    -			return response;
    +			try {
    +				const response =
    +					is_data_request || remote_id
    +						? redirect_json_response(e)
    +						: route?.page && is_action_json_request(event)
    +							? action_json_redirect(e)
    +							: redirect_response(e.status, e.location);
    +				add_cookies_to_headers(response.headers, new_cookies.values());
    +				return response;
    +			} catch (err) {
    +				return await handle_fatal_error(event, event_state, options, err);
    +			}
     		}
     		return await handle_fatal_error(event, event_state, options, e);
     	}
    
  • packages/kit/test/apps/basics/src/hooks.server.js+5 0 modified
    @@ -141,6 +141,11 @@ export const handle = sequence(
     	},
     	async ({ event, resolve }) => {
     		if (event.url.pathname.includes('/redirect/in-handle')) {
    +			const location = event.url.searchParams.get('location');
    +			if (location) {
    +				redirect(307, location);
    +			}
    +
     			if (event.url.search === '?throw') {
     				redirect(307, event.url.origin + '/redirect/c');
     			} else if (event.url.search.includes('cookies')) {
    
  • packages/kit/test/apps/basics/test/cross-platform/test.js+13 0 modified
    @@ -603,6 +603,19 @@ test.describe('Redirects', () => {
     		expect(page.url()).toBe(`${baseURL}/redirect`);
     	});
     
    +	test('invalid redirect location in handle hook returns 500 without crashing server', async ({
    +		request
    +	}) => {
    +		const bad_redirect = await request.get(
    +			'/redirect/in-handle?location=%2Fredirect%2Fc%0D%0Aset-cookie%3A%20evil%3D1'
    +		);
    +
    +		expect(bad_redirect.status()).toBe(500);
    +
    +		const follow_up = await request.get('/');
    +		expect(follow_up.status()).toBe(200);
    +	});
    +
     	test('sets cookies when redirect in handle hook', async ({ page, app, javaScriptEnabled }) => {
     		await page.goto('/cookies/set');
     		let span = page.locator('#cookie-value');
    
  • packages/kit/types/index.d.ts+1 1 modified
    @@ -2728,7 +2728,7 @@ declare module '@sveltejs/kit' {
     	 * @param status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). Must be in the range 300-308.
     	 * @param location The location to redirect to.
     	 * @throws {Redirect} This error instructs SvelteKit to redirect to the specified location.
    -	 * @throws {Error} If the provided status is invalid.
    +	 * @throws {Error} If the provided status is invalid or the location cannot be used as a header value.
     	 * */
     	export function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never;
     	/**
    

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.