From be89ae6f5eafd16c04fe054192a989ffc3a57bd8 Mon Sep 17 00:00:00 2001 From: Christian Sidak Date: Sun, 12 Apr 2026 11:24:11 -0700 Subject: [PATCH] Fix isPathWithinAllowedDirectories for UNC paths on Windows On Windows, path.normalize can strip a leading backslash from UNC paths (\\server\share becomes \server\share). When path.resolve is then called on this single-backslash path, it gets interpreted as drive-relative (e.g. C:\server\share), causing the allowed-directory check to always fail for UNC network paths. This introduces normalizePossiblyUNCPath which detects UNC paths and preserves the \\\\ prefix through normalization, rather than passing them through path.resolve which corrupts them. Fixes #3756 --- src/filesystem/path-validation.ts | 33 ++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/filesystem/path-validation.ts b/src/filesystem/path-validation.ts index 972e9c49d0..d74ca1b4cb 100644 --- a/src/filesystem/path-validation.ts +++ b/src/filesystem/path-validation.ts @@ -1,8 +1,35 @@ import path from 'path'; +/** + * Checks if a path is a UNC path (e.g. \\server\share). + */ +function isUNCPath(p: string): boolean { + return p.startsWith('\\\\'); +} + +/** + * Normalizes a path that may be a UNC path on Windows. + * + * On Windows, path.normalize can strip one leading backslash from UNC paths + * (e.g. \\server\share becomes \server\share), and then path.resolve + * interprets it as a drive-relative path (e.g. C:\server\share). This + * function preserves the UNC prefix through normalization. + */ +function normalizePossiblyUNCPath(p: string): string { + if (isUNCPath(p)) { + let normalized = path.normalize(p); + // path.normalize may strip a leading backslash from UNC paths + if (!normalized.startsWith('\\\\')) { + normalized = '\\' + normalized; + } + return normalized; + } + return path.resolve(path.normalize(p)); +} + /** * Checks if an absolute path is within any of the allowed directories. - * + * * @param absolutePath - The absolute path to check (will be normalized) * @param allowedDirectories - Array of absolute allowed directory paths (will be normalized) * @returns true if the path is within an allowed directory, false otherwise @@ -27,7 +54,7 @@ export function isPathWithinAllowedDirectories(absolutePath: string, allowedDire // Normalize the input path let normalizedPath: string; try { - normalizedPath = path.resolve(path.normalize(absolutePath)); + normalizedPath = normalizePossiblyUNCPath(absolutePath); } catch { return false; } @@ -51,7 +78,7 @@ export function isPathWithinAllowedDirectories(absolutePath: string, allowedDire // Normalize the allowed directory let normalizedDir: string; try { - normalizedDir = path.resolve(path.normalize(dir)); + normalizedDir = normalizePossiblyUNCPath(dir); } catch { return false; }