CVE-2023-29003 (published 2023-04-04T22:15Z)

SvelteKit is a web development framework. The SvelteKit framework offers developers an option to create simple REST APIs. This is done by defining a `+server.js` file, containing endpoint handlers for different HTTP methods.\n\nSvelteKit provides out-of-the-box cross-site request forgery (CSRF) protection to its users. While the implementation does a sufficient job in mitigating common CSRF attacks, prior to version 1.15.1, the protection can be bypassed by simply specifying a different `Content-Type` header value.\n\nIf abused, this issue will allow malicious requests to be submitted from third-party domains, which can allow execution of operations within the context of the victim's session, and in extreme scenarios can lead to unauthorized access to users’ accounts.\n\nSvelteKit 1.15.1 updates the `is_form_content_type` function call in the CSRF protection logic to include `text/plain`. As additional hardening of the CSRF protection mechanism against potential method overrides, SvelteKit 1.15.1 is now performing validation on `PUT`, `PATCH` and `DELETE` methods as well. This latter hardening is only needed to protect users who have put in some sort of `?_method= override` feature themselves in their `handle` hook, so that the request that resolve sees could be `PUT`/`PATCH`/`DELETE` when the browser issues a `POST` request.

CVSS v3 base score: 8.8, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-352
cwe_name: Cross-Site Request Forgery (CSRF)
description: The web application does not, or can not, sufficiently verify whether a well-formed, valid, consistent request was intentionally provided by the user who submitted the request.
extended_description: When a web server is designed to receive a request from a client without any mechanism for verifying that it was intentionally sent, then it might be possible for an attacker to trick a client into making an unintentional request to the web server which will be treated as an authentic request. This can be done via a URL, image load, XMLHttpRequest, etc. and can result in exposure of data or unintended code execution.
         

Fix information:
repo_url: https://github.com/sveltejs/kit
commit_details: repo_url: https://github.com/sveltejs/kit
author: Ben McCann
author_date: 2023-04-04 10:42:00-07:00
msg: Merge pull request from GHSA-5p75-vc5g-8rv2

* fix: address security advisory CVE-2023-29003 by enabling CSRF protection for plain/text requests

* Protect PUT/PATCH/DELETE. Add comment explicitly mentioning CSRF

* update docs

* update changeset

* Update packages/kit/types/index.d.ts

Co-authored-by: Conduitry <git@chor.date>

* Update packages/kit/types/index.d.ts

* Update cool-lies-fly.md

* Update packages/kit/src/utils/http.js

Co-authored-by: Dominik G. <dominik.goepel@gmx.de>

* Update packages/kit/types/index.d.ts

Co-authored-by: Dominik G. <dominik.goepel@gmx.de>

* test(csrf): include additional methods and content-types

---------

Co-authored-by: Conduitry <git@chor.date>
Co-authored-by: Dominik G. <dominik.goepel@gmx.de>
repository: repo_url: https://github.com/sveltejs/kit
repo_name: sveltejs/kit
description: web development, streamlined
repo_language: JavaScript
owner: sveltejs
file_changes: filename: cool-lies-fly.md
change_type: ModificationType.ADD
diff: @@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+fix: address security advisory CVE-2023-29003 by including `text/plain` and `PUT`/`PATCH`/`DELETE` requests in set of blocked cross-origin requests for CSRF protection

programming_language: SQL
filename: respond.js
change_type: ModificationType.MODIFY
diff: @@ -51,9 +51,12 @@ export async function respond(request, options, manifest, state) {
 
 	if (options.csrf_check_origin) {
 		const forbidden =
-			request.method === 'POST' &&
-			request.headers.get('origin') !== url.origin &&
-			is_form_content_type(request);
+			is_form_content_type(request) &&
+			(request.method === 'POST' ||
+				request.method === 'PUT' ||
+				request.method === 'PATCH' ||
+				request.method === 'DELETE') &&
+			request.headers.get('origin') !== url.origin;
 
 		if (forbidden) {
 			const csrf_error = error(403, `Cross-site ${request.method} form submissions are forbidden`);

programming_language: JavaScript
filename: http.js
change_type: ModificationType.MODIFY
diff: @@ -68,5 +68,12 @@ export function is_content_type(request, ...types) {
  * @param {Request} request
  */
 export function is_form_content_type(request) {
-	return is_content_type(request, 'application/x-www-form-urlencoded', 'multipart/form-data');
+	// These content types must be protected against CSRF
+	// https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/enctype
+	return is_content_type(
+		request,
+		'application/x-www-form-urlencoded',
+		'multipart/form-data',
+		'text/plain'
+	);
 }

programming_language: TypeScript
filename: server.test.js
change_type: ModificationType.MODIFY
diff: @@ -58,15 +58,27 @@ test.describe('Cookies', () => {
 
 test.describe('CSRF', () => {
 	test('Blocks requests with incorrect origin', async ({ baseURL }) => {
-		const res = await fetch(`${baseURL}/csrf`, {
-			method: 'POST',
-			headers: {
-				'content-type': 'application/x-www-form-urlencoded'
+		const content_types = [
+			'application/x-www-form-urlencoded',
+			'multipart/form-data',
+			'text/plain'
+		];
+		const methods = ['POST', 'PUT', 'PATCH', 'DELETE'];
+		for (const method of methods) {
+			for (const content_type of content_types) {
+				const res = await fetch(`${baseURL}/csrf`, {
+					method,
+					headers: {
+						'content-type': content_type
+					}
+				});
+				const message = `request method: ${method}, content-type: ${content_type}`;
+				expect(res.status, message).toBe(403);
+				expect(await res.text(), message).toBe(
+					`Cross-site ${method} form submissions are forbidden`
+				);
 			}
-		});
-
-		expect(res.status).toBe(403);
-		expect(await res.text()).toBe('Cross-site POST form submissions are forbidden');
+		}
 	});
 });
 

programming_language: TypeScript
filename: index.d.ts
change_type: ModificationType.MODIFY
diff: @@ -328,13 +328,13 @@ export interface KitConfig {
 		reportOnly?: CspDirectives;
 	};
 	/**
-	 * Protection against [cross-site request forgery](https://owasp.org/www-community/attacks/csrf) attacks.
+	 * Protection against [cross-site request forgery (CSRF)](https://owasp.org/www-community/attacks/csrf) attacks.
 	 */
 	csrf?: {
 		/**
-		 * Whether to check the incoming `origin` header for `POST` form submissions and verify that it matches the server's origin.
+		 * Whether to check the incoming `origin` header for `POST`, `PUT`, `PATCH`, or `DELETE` form submissions and verify that it matches the server's origin.
 		 *
-		 * To allow people to make `POST` form submissions to your app from other origins, you will need to disable this option. Be careful!
+		 * To allow people to make `POST`, `PUT`, `PATCH`, or `DELETE` requests with a `Content-Type` of `application/x-www-form-urlencoded`, `multipart/form-data`, or `text/plain` to your app from other origins, you will need to disable this option. Be careful!
 		 * @default true
 		 */
 		checkOrigin?: boolean;

programming_language: TypeScript