From 5aa8f71384fc425f03e5c6c0ca4755c6e2d7f146 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 25 Mar 2026 23:39:18 +0000 Subject: [PATCH] Fix Path Traversal vulnerability in video upload API Sanitized the user-provided `file.name` using `path.basename()` before writing to the local `/tmp/omni/video` directory to prevent directory traversal attacks (e.g., `../../../../etc/passwd`). Co-authored-by: Cukurikik <266119688+Cukurikik@users.noreply.github.com> --- .jules/sentinel.md | 5 +++++ src/app/api/video/[tool]/route.ts | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 2ceab100..0e992fa8 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -2,3 +2,8 @@ **Vulnerability:** Raw error objects from FFmpeg and browser APIs (`error.message` and `console.error`) were being rendered directly in the user interface and browser console. **Learning:** Returning unhandled exception messages to the client risks exposing internal stack traces, system paths, and unexpected framework vulnerabilities to potential attackers. **Prevention:** Catch error blocks should log a sanitized version of the error or omit sensitive details, while the state presented to the user should be a generic, friendly, and secure fallback message (e.g. "Processing failed securely"). + +## 2024-03-25 - Prevent Path Traversal in Server File Uploads +**Vulnerability:** In `src/app/api/video/[tool]/route.ts`, the file upload endpoint used the unsanitized `file.name` to construct the `inputPath` where the server would save the user's file (`${tmpDir}/${crypto.randomUUID()}_${file.name}`). This permitted a Path Traversal vulnerability where an attacker could upload a file with a name containing `../` to write arbitrary files outside the intended `/tmp/omni/video` directory, such as `../../../../../etc/passwd`. +**Learning:** Even if randomizing the start of a file path (using `crypto.randomUUID()`), appending user-controlled input to the end of a path without sanitization still allows the directory segments to traverse up the file tree. +**Prevention:** Always sanitize filenames from user uploads using `path.basename(file.name)` to strip out any directory paths and safely construct paths using `path.join()`. diff --git a/src/app/api/video/[tool]/route.ts b/src/app/api/video/[tool]/route.ts index a7307430..9c552d93 100644 --- a/src/app/api/video/[tool]/route.ts +++ b/src/app/api/video/[tool]/route.ts @@ -126,7 +126,10 @@ export async function POST( const tmpDir = `/tmp/omni/video`; await fs.mkdir(tmpDir, { recursive: true }); - const inputPath = `${tmpDir}/${crypto.randomUUID()}_${file.name}`; + + // Prevent path traversal by extracting just the filename + const safeFileName = path.basename(file.name); + const inputPath = path.join(tmpDir, `${crypto.randomUUID()}_${safeFileName}`); // Write file to disk const arrayBuffer = await file.arrayBuffer();