fix(core): fix workspace path validation with file:// URLs and encoded spaces

Fixed a bug in validateWorkspacePath where splitting by path.delimiter on Unix would break file:// URLs due to colons. Added splitWorkspacePaths helper to handle this. Updated tests to use file:// URLs for encoded paths and added a test case to ensure literal %20 in cwd is not incorrectly resolved.
This commit is contained in:
Akhilesh Kumar 2026-05-21 17:32:18 +00:00
parent 2f4fc17230
commit ef303eb84a
2 changed files with 17 additions and 9 deletions

View file

@ -468,7 +468,7 @@ describe('ide-connection-utils', () => {
describe('with special characters and encoding', () => {
it('should return true for a URI-encoded path with spaces', () => {
const workspaceDir = path.resolve('/test/my workspace');
const workspacePath = '/test/my%20workspace';
const workspacePath = pathToFileURL(workspaceDir).toString();
const cwd = path.join(workspaceDir, 'sub-dir');
const result = validateWorkspacePath(workspacePath, cwd);
expect(result.isValid).toBe(true);
@ -476,7 +476,7 @@ describe('ide-connection-utils', () => {
it('should return true for a URI-encoded path with Korean characters', () => {
const workspaceDir = path.resolve('/test/테스트');
const workspacePath = '/test/%ED%85%8C%EC%8A%A4%ED%8A%B8'; // "테스트"
const workspacePath = pathToFileURL(workspaceDir).toString();
const cwd = path.join(workspaceDir, 'sub-dir');
const result = validateWorkspacePath(workspacePath, cwd);
expect(result.isValid).toBe(true);
@ -494,7 +494,7 @@ describe('ide-connection-utils', () => {
const workspaceDir2 = path.resolve('/test/테스트');
const workspacePath = [
workspaceDir1,
'/test/%ED%85%8C%EC%8A%A4%ED%8A%B8', // "테스트"
pathToFileURL(workspaceDir2).toString(),
].join(path.delimiter);
const cwd = path.join(workspaceDir2, 'sub-dir');
const result = validateWorkspacePath(workspacePath, cwd);
@ -536,17 +536,18 @@ describe('ide-connection-utils', () => {
expectedValid: true,
},
{
description: 'should return true when workspace has encoded spaces',
workspacePath: path.resolve('test', 'my ws').replace(/ /g, '%20'),
description:
'should return true when workspace has encoded spaces in file:// URL',
workspacePath: pathToFileURL(path.resolve('test', 'my ws')).toString(),
cwd: path.resolve('test', 'my ws'),
expectedValid: true,
},
{
description:
'should return true when cwd needs normalization matching workspace',
'should return false when cwd has literal %20 and workspace has space',
workspacePath: path.resolve('test', 'my ws'),
cwd: path.resolve('test', 'my ws').replace(/ /g, '%20'),
expectedValid: true,
expectedValid: false,
},
])('$description', ({ workspacePath, cwd, expectedValid }) => {
expect(validateWorkspacePath(workspacePath, cwd)).toMatchObject({

View file

@ -33,6 +33,14 @@ export type ConnectionConfig = {
stdio?: StdioConfig;
};
function splitWorkspacePaths(paths: string): string[] {
if (process.platform === 'win32') {
return paths.split(';');
} else {
return paths.split(/:(?!\/\/)/);
}
}
export function validateWorkspacePath(
ideWorkspacePath: string | undefined,
cwd: string,
@ -51,8 +59,7 @@ export function validateWorkspacePath(
};
}
const ideWorkspacePaths = ideWorkspacePath
.split(path.delimiter)
const ideWorkspacePaths = splitWorkspacePaths(ideWorkspacePath)
.map((p) => resolveToRealPath(p))
.filter((e) => !!e);
const realCwd = resolveToRealPath(cwd);