From b760cde52e8a7743aa4e1430ee4037aebb5f510b Mon Sep 17 00:00:00 2001 From: Serhat Dolmaci Date: Mon, 29 Jun 2026 23:43:54 +0300 Subject: [PATCH] fix(path-validation): resolve symlinks in assertWithinDir path.resolve() does not follow symlinks, allowing a symlink inside the allowed directory pointing outside to bypass the path traversal check. Use fs.realpathSync() to resolve symlinks first. --- src/lib/path-validation.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lib/path-validation.ts b/src/lib/path-validation.ts index 4e932a2..cde3853 100644 --- a/src/lib/path-validation.ts +++ b/src/lib/path-validation.ts @@ -1,13 +1,15 @@ +import fs from 'fs'; import path from 'path'; /** * Validates that a resolved path is within the given directory. + * Follows symlinks to prevent symlink-based path traversal. * Throws if the path escapes the directory (path traversal). * Returns the resolved (normalized) path. */ export function assertWithinDir(targetPath: string, allowedDir: string): string { - const resolved = path.resolve(targetPath); - const dir = path.resolve(allowedDir); + const resolved = fs.realpathSync(targetPath); + const dir = fs.realpathSync(allowedDir); if (!resolved.startsWith(dir + path.sep) && resolved !== dir) { throw new Error(`Path traversal detected: ${resolved} is outside allowed directory ${dir}`); }