CVE-2024-36128 (published 2024-06-03T15:15Z)

Directus is a real-time API and App dashboard for managing SQL database content. Prior to 10.11.2, providing a non-numeric length value to the random string generation utility will create a memory issue breaking the capability to generate random strings platform wide. This creates a denial of service situation where logged in sessions can no longer be refreshed as sessions depend on the capability to generate a random session ID. This vulnerability is fixed in 10.11.2.


Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/directus/directus
commit_details: repo_url: https://github.com/directus/directus
author: Zehir
author_date: 2024-05-26 15:13:17+02:00
msg: Fix #22572 Invalid query for random string (#22573)

* Fix #22572 Invalid query for random string

* Add changeset

* Run prettier

* Fix unit tests warnings

* redo validation with Joi

* make validation on object level

documents itself and is cleaner to expand on

* Update changeset

* Allow integer only

* Require min value of 1

* Report as query error, ignore unknown queries

---------

Co-authored-by: Daniel Biegler <DanielBiegler@users.noreply.github.com>
Co-authored-by: Pascal Jufer <pascal-jufer@bluewin.ch>
repository: repo_url: https://github.com/directus/directus
repo_name: directus/directus
description: The Modern Data Stack 🐰 — Directus is an instant REST+GraphQL API and intuitive no-code data collaboration app for any SQL database.
repo_language: TypeScript
owner: directus
file_changes: filename: large-pans-dance.md
change_type: ModificationType.ADD
diff: @@ -0,0 +1,5 @@
+---
+"@directus/api": patch
+---
+
+Fixed an issue where calling `/random/string` with an invalid length param could prevent creation of valid sessions until next restart

programming_language: Markdown
filename: utils.ts
change_type: ModificationType.MODIFY
diff: @@ -14,18 +14,20 @@ import { sanitizeQuery } from '../utils/sanitize-query.js';
 
 const router = Router();
 
+const randomStringSchema = Joi.object<{ length: number }>({
+	length: Joi.number().integer().min(1).max(500).default(32),
+});
+
 router.get(
 	'/random/string',
 	asyncHandler(async (req, res) => {
 		const { nanoid } = await import('nanoid');
 
-		if (req.query && req.query['length'] && Number(req.query['length']) > 500) {
-			throw new InvalidQueryError({ reason: `"length" can't be more than 500 characters` });
-		}
+		const { error, value } = randomStringSchema.validate(req.query, { allowUnknown: true });
 
-		const string = nanoid(req.query?.['length'] ? Number(req.query['length']) : 32);
+		if (error) throw new InvalidQueryError({ reason: error.message });
 
-		return res.json({ data: string });
+		return res.json({ data: nanoid(value.length) });
 	}),
 );
 

programming_language: TypeScript
filename: index.ts
change_type: ModificationType.MODIFY
diff: @@ -2536,11 +2536,11 @@ export class GraphQLService {
 				resolve: async (_, args) => {
 					const { nanoid } = await import('nanoid');
 
-					if (args['length'] && Number(args['length']) > 500) {
-						throw new InvalidPayloadError({ reason: `"length" can't be more than 500 characters` });
+					if (args['length'] !== undefined && (args['length'] < 1 || args['length'] > 500)) {
+						throw new InvalidPayloadError({ reason: `"length" must be between 1 and 500` });
 					}
 
-					return nanoid(args['length'] ? Number(args['length']) : 32);
+					return nanoid(args['length'] ? args['length'] : 32);
 				},
 			},
 			utils_hash_generate: {

programming_language: TypeScript