From 928ab309196a281cb22a208c52f65d0eed563a68 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Sun, 26 Jul 2026 19:40:48 -0700 Subject: [PATCH] test(runtime): stop implying the folder-workspace escape guard is load-bearing The two `..` tests both passed with the guard deleted: child repos are already filtered to those inside the folder root, so any path a match could accept is inside the folder anyway. Replace the tautological test with one that pins the real behavior (a `..` path normalizing back inside still routes) and label the guard as defense-in-depth against the candidate filter widening. Co-authored-by: Orca --- src/main/runtime/folder-workspace-child-repos.test.ts | 10 ++++++++++ src/main/runtime/folder-workspace-child-repos.ts | 6 ++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/runtime/folder-workspace-child-repos.test.ts b/src/main/runtime/folder-workspace-child-repos.test.ts index 708bf56045e..0c339c96bbe 100644 --- a/src/main/runtime/folder-workspace-child-repos.test.ts +++ b/src/main/runtime/folder-workspace-child-repos.test.ts @@ -54,6 +54,16 @@ describe('matchFolderWorkspaceChildRepo', () => { expect(matchFolderWorkspaceChildRepo([API, OUTSIDE], FOLDER, '../other/x.ts')).toBeNull() }) + it('routes a `..` path that normalizes back inside the workspace', () => { + // Why: normalization, not the escape guard, is what decides this. A path can + // only reach a child repo if it is already inside the folder, since child repos + // are filtered to the folder — so the guard rejects nothing a match would have + // accepted. It stays as defense-in-depth if that filter ever changes. + expect( + matchFolderWorkspaceChildRepo([API], FOLDER, 'fint_api/../../fint/fint_api/src/app.ts') + ).toEqual({ repo: API, rebasedRelativePath: 'src/app.ts' }) + }) + it('returns null for a path in the folder but outside every child repo', () => { expect(matchFolderWorkspaceChildRepo([API], FOLDER, 'README.md')).toBeNull() }) diff --git a/src/main/runtime/folder-workspace-child-repos.ts b/src/main/runtime/folder-workspace-child-repos.ts index ffb59a6f100..0079d951798 100644 --- a/src/main/runtime/folder-workspace-child-repos.ts +++ b/src/main/runtime/folder-workspace-child-repos.ts @@ -39,8 +39,10 @@ export function matchFolderWorkspaceChildRepo( return null } const absolutePath = resolveRuntimePath(folderPath, relativePath) - // Why: a `..` segment can escape the workspace, which must not silently - // resolve to an unrelated repo the user never opened. + // Why: a `..` segment must not silently resolve to a repo the user never opened. + // Defense-in-depth today — the loop below only considers repos already inside + // `folderPath`, so anything it could match is inside the folder anyway. This + // stops that from being load-bearing if the candidate filter ever widens. if (relativePathInsideRoot(folderPath, absolutePath) === null) { return null }