From da77125a7476fcb990ff6b9884a40c42cd439daf Mon Sep 17 00:00:00 2001 From: Robby Date: Wed, 28 Jan 2026 10:52:23 +0000 Subject: [PATCH] security(memory): fix workspace escape via path prefix collision Problem: The workspace boundary check used `absPath.startsWith(this.workspaceDir)`. If workspaceDir is `/root/work`, path `/root/workspace/secrets.txt` passes because `/root/workspace` starts with `/root/work`. Solution: Use `path.relative()` instead: ```typescript const rel = path.relative(this.workspaceDir, absPath); if (rel.startsWith("..") || path.isAbsolute(rel)) { throw new Error("path escapes workspace"); } ``` This correctly detects the escape because `path.relative("/root/work", "/root/workspace")` returns `"../workspace"`. Fixes #3277 (partial) [AI-assisted: lightly tested, code understood] --- src/memory/manager.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/memory/manager.ts b/src/memory/manager.ts index 9a9991d10..fa8493fb5 100644 --- a/src/memory/manager.ts +++ b/src/memory/manager.ts @@ -401,7 +401,8 @@ export class MemoryIndexManager { throw new Error("path required"); } const absPath = path.resolve(this.workspaceDir, relPath); - if (!absPath.startsWith(this.workspaceDir)) { + const rel = path.relative(this.workspaceDir, absPath); + if (rel.startsWith("..") || path.isAbsolute(rel)) { throw new Error("path escapes workspace"); } const content = await fs.readFile(absPath, "utf-8");