From 5c16dd4ad6fab20783edaf5be53a0df99b7d0878 Mon Sep 17 00:00:00 2001 From: Ahmed Hindy Date: Thu, 25 Jun 2026 22:57:39 +0300 Subject: [PATCH] Fix Windows allowedRoots bypass --- src/roots.test.ts | 7 +++++++ src/roots.ts | 7 +++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/roots.test.ts b/src/roots.test.ts index 96d479a0..90bdaa24 100644 --- a/src/roots.test.ts +++ b/src/roots.test.ts @@ -24,3 +24,10 @@ assert.equal( resolveAllowedPath("~/file.txt", "/workspace", ["/workspace"]), resolve("/workspace", "~/file.txt"), ); + +if (process.platform === "win32") { + assert.throws( + () => assertAllowedPath("C:\\Users\\Administrator", ["G:\\Projects\\Dev\\Github\\devspace"]), + /Path is outside allowed roots/, + ); +} diff --git a/src/roots.ts b/src/roots.ts index 0ebd49ab..214ffb2b 100644 --- a/src/roots.ts +++ b/src/roots.ts @@ -1,5 +1,5 @@ import { homedir } from "node:os"; -import { relative, resolve, sep } from "node:path"; +import { isAbsolute, relative, resolve, sep } from "node:path"; export class AccessDeniedError extends Error { constructor(message: string) { @@ -24,7 +24,10 @@ export function isPathInsideRoot(path: string, root: string): boolean { return ( relationship === "" || - (!relationship.startsWith("..") && relationship !== ".." && !relationship.includes(`..${sep}`)) + (!isAbsolute(relationship) && + !relationship.startsWith("..") && + relationship !== ".." && + !relationship.includes(`..${sep}`)) ); }