From 00699cd727502fe511e51111df38c3659c7edf1c Mon Sep 17 00:00:00 2001 From: Lygggggg Date: Fri, 10 Apr 2026 09:56:09 +0800 Subject: [PATCH 1/2] fix(workspace): use path.isAbsolute() for Windows path compatibility The worktrees endpoint rejected Windows absolute paths (e.g. C:\...) because it checked repoRoot.startsWith('/') which only matches Unix paths. Replace with Node.js path.isAbsolute() which handles both Windows and Unix paths correctly. isAbsolute was already imported but unused for this check. Co-Authored-By: Claude Opus 4.6 --- packages/api/src/routes/workspace.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/api/src/routes/workspace.ts b/packages/api/src/routes/workspace.ts index 58835cf48..b99934bda 100644 --- a/packages/api/src/routes/workspace.ts +++ b/packages/api/src/routes/workspace.ts @@ -280,7 +280,7 @@ export const workspaceRoutes: FastifyPluginAsync = async (ap app.get<{ Querystring: { repoRoot?: string } }>('/api/workspace/worktrees', async (request, reply) => { const { repoRoot } = request.query; if (repoRoot) { - if (!repoRoot.startsWith('/')) { + if (!isAbsolute(repoRoot)) { reply.status(400); return { error: 'repoRoot must be an absolute path' }; } From 227d5ee76d0c41cfb249f85e15d7bb2f2928dfab Mon Sep 17 00:00:00 2001 From: Lygggggg Date: Fri, 10 Apr 2026 10:05:11 +0800 Subject: [PATCH 2/2] test(workspace): add Windows path validation regression test Verify that isAbsolute() correctly accepts Windows absolute paths (C:\..., C:/..., UNC \server\share) and rejects relative paths. Prevents regression of the startsWith('/') bug. Closes #414 Co-Authored-By: Claude Opus 4.6 --- .../api/test/workspace-windows-path.test.js | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 packages/api/test/workspace-windows-path.test.js diff --git a/packages/api/test/workspace-windows-path.test.js b/packages/api/test/workspace-windows-path.test.js new file mode 100644 index 000000000..add41e52e --- /dev/null +++ b/packages/api/test/workspace-windows-path.test.js @@ -0,0 +1,36 @@ +import assert from 'node:assert/strict'; +import { isAbsolute } from 'node:path'; +import { describe, it } from 'node:test'; + +describe('workspace worktrees repoRoot validation (Windows compat)', () => { + // The route handler uses isAbsolute() to validate repoRoot. + // Previously it used startsWith('/') which rejected Windows paths. + + it('accepts Unix absolute path', () => { + assert.ok(isAbsolute('/home/user/project')); + }); + + it('accepts Windows absolute path with backslash', () => { + assert.ok(isAbsolute('C:\\Personal\\AIProjects\\test-project')); + }); + + it('accepts Windows absolute path with forward slash', () => { + assert.ok(isAbsolute('C:/Personal/AIProjects/test-project')); + }); + + it('accepts UNC path', () => { + assert.ok(isAbsolute('\\\\server\\share\\folder')); + }); + + it('rejects relative path', () => { + assert.ok(!isAbsolute('relative/path')); + }); + + it('rejects dot-relative path', () => { + assert.ok(!isAbsolute('./src/index.ts')); + }); + + it('rejects parent-relative path', () => { + assert.ok(!isAbsolute('../etc/passwd')); + }); +});