Browse Source

fix: handle forward-slash drive roots and UNC paths in validation

Broaden the trailing-slash exemption to recognize both C:\ and C:/ as
drive roots. Tighten the client-side absolute path check to require a
separator after the drive letter and accept UNC paths (\\server\share).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
handoff-20260429-1057
shrimbly 5 months ago
parent
commit
9624c44e4a
  1. 7
      src/app/api/browse-directory/__tests__/route.test.ts
  2. 2
      src/app/api/browse-directory/route.ts
  3. 4
      src/components/ProjectSetupModal.tsx
  4. 2
      src/components/__tests__/ProjectSetupModal.test.tsx

7
src/app/api/browse-directory/__tests__/route.test.ts

@ -32,11 +32,16 @@ describe("normalizeSelectedPath", () => {
.toBe("C:\\Users\\guy");
});
it("should preserve Windows drive root", () => {
it("should preserve Windows drive root with backslash", () => {
expect(normalizeSelectedPath("C:\\", "win32"))
.toBe("C:\\");
});
it("should preserve Windows drive root with forward slash", () => {
expect(normalizeSelectedPath("C:/", "win32"))
.toBe("C:/");
});
it("should preserve Unix root /", () => {
expect(normalizeSelectedPath("/", "darwin"))
.toBe("/");

2
src/app/api/browse-directory/route.ts

@ -26,7 +26,7 @@ export function normalizeSelectedPath(selectedPath: string, platform: string): s
// Remove trailing slash/backslash (except root paths like "/" or "C:\")
if (selectedPath.length > 1 && (selectedPath.endsWith("/") || selectedPath.endsWith("\\"))) {
if (!(platform === "win32" && /^[A-Za-z]:\\$/.test(selectedPath))) {
if (!(platform === "win32" && /^[A-Za-z]:[\\\/]$/.test(selectedPath))) {
selectedPath = selectedPath.slice(0, -1);
}
}

4
src/components/ProjectSetupModal.tsx

@ -200,8 +200,8 @@ export function ProjectSetupModal({
}
const trimmedPath = directoryPath.trim();
if (!(trimmedPath.startsWith("/") || /^[A-Za-z]:/.test(trimmedPath))) {
setError("Project directory must be an absolute path (starting with / or a drive letter)");
if (!(trimmedPath.startsWith("/") || /^[A-Za-z]:[\\\/]/.test(trimmedPath) || trimmedPath.startsWith("\\\\"))) {
setError("Project directory must be an absolute path (starting with /, a drive letter, or a UNC path)");
return;
}

2
src/components/__tests__/ProjectSetupModal.test.tsx

@ -407,7 +407,7 @@ describe("ProjectSetupModal", () => {
await waitFor(() => {
expect(
screen.getByText("Project directory must be an absolute path (starting with / or a drive letter)")
screen.getByText("Project directory must be an absolute path (starting with /, a drive letter, or a UNC path)")
).toBeInTheDocument();
});
expect(onSave).not.toHaveBeenCalled();

Loading…
Cancel
Save