From 6666be06524ef250a5dfbf94315cff75b228933e Mon Sep 17 00:00:00 2001 From: Nix Date: Tue, 24 Mar 2026 21:33:24 +0530 Subject: [PATCH] fix(security): resolve symlinks in path-suggestions home directory check (fixes #52) (#54) The isWithinHome() check used path.relative() which is purely string-based and does not follow symlinks. A symlink inside the home directory pointing to an external path would bypass the containment check, allowing directory listing of arbitrary filesystem locations. Now uses fs.realpathSync() to resolve symlinks before the containment comparison, ensuring the real filesystem path is validated. Co-authored-by: ThankNIXlater --- src/app/api/path-suggestions/route.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/app/api/path-suggestions/route.ts b/src/app/api/path-suggestions/route.ts index 697066d..3179f66 100644 --- a/src/app/api/path-suggestions/route.ts +++ b/src/app/api/path-suggestions/route.ts @@ -42,8 +42,18 @@ const normalizeQuery = (query: string): string => { return `~/${withoutLeading}`; }; +const resolveRealPath = (value: string): string => { + try { + return fs.realpathSync(value); + } catch { + return path.resolve(value); + } +}; + const isWithinHome = (target: string, home: string): boolean => { - const relative = path.relative(home, target); + const resolvedTarget = resolveRealPath(target); + const resolvedHome = resolveRealPath(home); + const relative = path.relative(resolvedHome, resolvedTarget); if (!relative) return true; return !relative.startsWith("..") && !path.isAbsolute(relative); };