diff --git a/src/main/ipc/worktree-logic.test.ts b/src/main/ipc/worktree-logic.test.ts index 73231eab8fa..0f1c96dab32 100644 --- a/src/main/ipc/worktree-logic.test.ts +++ b/src/main/ipc/worktree-logic.test.ts @@ -111,6 +111,12 @@ describe('ensurePathWithinWorkspace', () => { 'Invalid worktree path' ) }) + + it('allows workspace children whose names start with dot-dot text', () => { + const result = ensurePathWithinWorkspace('/workspace/..repo/feature', '/workspace') + + expect(result).toBe(resolve('/workspace/..repo/feature')) + }) }) describe('computeBranchName', () => { diff --git a/src/main/ipc/worktree-logic.ts b/src/main/ipc/worktree-logic.ts index e94dfd6a495..6aabba36680 100644 --- a/src/main/ipc/worktree-logic.ts +++ b/src/main/ipc/worktree-logic.ts @@ -1,4 +1,4 @@ -import { basename, join, resolve, relative, isAbsolute, posix, win32 } from 'path' +import { basename, join, resolve, relative, isAbsolute, posix, sep, win32 } from 'path' import type { GitWorktreeInfo, Worktree, WorktreeMeta } from '../../shared/types' import { splitWorktreeId } from '../../shared/worktree-id' import { DEFAULT_WORKSPACE_STATUS_ID } from '../../shared/workspace-statuses' @@ -57,7 +57,7 @@ export function ensurePathWithinWorkspace(targetPath: string, workspaceDir: stri const resolvedTargetPath = resolve(targetPath) const rel = relative(resolvedWorkspaceDir, resolvedTargetPath) - if (isAbsolute(rel) || rel.startsWith('..')) { + if (isAbsolute(rel) || rel === '..' || rel.startsWith(`..${sep}`)) { throw new Error('Invalid worktree path') }