From 0666997b22ca00645346e7abbf736c01a401c768 Mon Sep 17 00:00:00 2001 From: ifeoluwaaj Date: Sun, 7 Jun 2026 23:03:16 +0000 Subject: [PATCH] fix(security): validate missionId in creator-mission to prevent path traversal - Add validateMissionId() helper that enforces alphanumeric, hyphens, and underscores only - Block path traversal attempts like '../../etc/passwd' in readCreatorMissionTrace() - Log invalid missionId attempts and return null safely - Prevents user-supplied missionId from resolving outside the state directory --- src/lib/server/creator-mission.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/lib/server/creator-mission.ts b/src/lib/server/creator-mission.ts index 456f3667..b1a54638 100644 --- a/src/lib/server/creator-mission.ts +++ b/src/lib/server/creator-mission.ts @@ -366,6 +366,14 @@ function creatorMissionDir(stateDir = spawnerStateDir()): string { return path.join(stateDir, 'creator-missions'); } +/** + * Validates that a missionId contains only safe characters and cannot be used for path traversal. + * Mission IDs should be alphanumeric with hyphens/underscores only. + */ +function validateMissionId(missionId: string): boolean { + return /^[a-zA-Z0-9_-]+$/.test(missionId); +} + function pendingLoadPath(stateDir = spawnerStateDir()): string { return path.join(stateDir, 'pending-load.json'); } @@ -1653,6 +1661,10 @@ export async function readCreatorMissionTrace( ): Promise { const missionId = input.missionId?.trim(); if (missionId) { + if (!validateMissionId(missionId)) { + console.error(`Invalid missionId format: ${missionId}`); + return null; + } const filePath = creatorMissionPath(missionId, stateDir); if (!existsSync(filePath)) return null; return parseCreatorMissionTraceFile(await readFile(filePath, 'utf-8'));