From 870f92d208f63ed28abfd5212be9c1e2ce552d5b Mon Sep 17 00:00:00 2001 From: Marko Djordjevic Date: Wed, 18 Feb 2026 10:58:54 +0100 Subject: [PATCH] feat: add run_id format validation in DELETE training/runs endpoint Validate that run_id matches /^[a-zA-Z0-9_-]+$ regex before interpolating into the API URL. Returns HTTP 400 with 'Invalid run_id format' error if validation fails. This prevents potential URL injection attacks and invalid identifier usage. --- openspec/changes/code-review-fix/tasks.md | 2 +- src/app/api/training/runs/[run_id]/route.ts | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/openspec/changes/code-review-fix/tasks.md b/openspec/changes/code-review-fix/tasks.md index f2a6df8..6da5d84 100644 --- a/openspec/changes/code-review-fix/tasks.md +++ b/openspec/changes/code-review-fix/tasks.md @@ -11,7 +11,7 @@ ## 2. Security Critical — Input Validation & CORS -- [ ] 2.1 `[haiku]` Validate `run_id` matches `/^[a-zA-Z0-9_-]+$/` in `src/app/api/training/runs/[run_id]/route.ts` before interpolation +- [x] 2.1 `[haiku]` Validate `run_id` matches `/^[a-zA-Z0-9_-]+$/` in `src/app/api/training/runs/[run_id]/route.ts` before interpolation - [ ] 2.2 `[sonnet]` Validate `run_id` format and use `Path.resolve()` + directory containment check in `services/ml/app/main.py` (model load at line 1203, delete at line 1312) - [ ] 2.3 `[sonnet]` Add file size check (reject >10MB) and row count limit (500,000) to `src/app/api/upload/route.ts` - [ ] 2.4 `[haiku]` Add file type validation (`.csv` extension, text MIME type) to `src/app/api/upload/route.ts` diff --git a/src/app/api/training/runs/[run_id]/route.ts b/src/app/api/training/runs/[run_id]/route.ts index da05d9c..1ac3773 100644 --- a/src/app/api/training/runs/[run_id]/route.ts +++ b/src/app/api/training/runs/[run_id]/route.ts @@ -8,6 +8,16 @@ export async function DELETE( { params }: { params: Promise<{ run_id: string }> } ) { const { run_id } = await params; + + // Validate run_id format before using in interpolation + const RUN_ID_REGEX = /^[a-zA-Z0-9_-]+$/; + if (!RUN_ID_REGEX.test(run_id)) { + return NextResponse.json( + { error: 'Invalid run_id format' }, + { status: 400 } + ); + } + const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), INFERENCE_API_TIMEOUT);