Skip to content

[Fix] use path.sep in migrateWorkspace nested-path guard#548

Open
advancedresearcharray wants to merge 2 commits into
clawwork-ai:mainfrom
advancedresearcharray:fix/migrate-workspace-path-sep-382
Open

[Fix] use path.sep in migrateWorkspace nested-path guard#548
advancedresearcharray wants to merge 2 commits into
clawwork-ai:mainfrom
advancedresearcharray:fix/migrate-workspace-path-sep-382

Conversation

@advancedresearcharray

Copy link
Copy Markdown
Contributor

Closes #382

Summary

migrateWorkspace used a hardcoded / when checking whether the new workspace path is inside the old one. On Windows, path.resolve() returns backslash paths, so the guard never fired and a recursive copy loop was possible.

Uses path.sep (same pattern as ensureTaskDir in the same file). Also adds a case-insensitive path guard for Windows/macOS.

Test plan

  • pnpm --filter @clawwork/desktop test (includes workspace-init.test.ts)
  • Unix nested-path rejection + win32 separator regression test

Release note

Fixed workspace migration allowing a nested destination path on Windows, which could fill the disk with recursive copies.

advancedresearcharray and others added 2 commits June 19, 2026 08:10
On Windows, resolve() returns backslash paths so the hardcoded '/'
prefix check never matched nested destinations. Use path.sep like
ensureTaskDir already does in the same module.

Closes clawwork-ai#382.

Signed-off-by: advancedresearcharray <advancedresearcharray@users.noreply.github.com>
Address review feedback on clawwork-ai#510: normalize resolved paths before
comparing on win32/darwin and use win32.sep for nested checks on Windows.

Closes clawwork-ai#382.

Signed-off-by: root <root@thirtynince.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

Copy link
Copy Markdown
Contributor

Hi @advancedresearcharray,
Thanks for your pull request!
If the PR is ready, use the /auto-cc command to assign Reviewer to Review.
We will review it shortly.

Details

Instructions for interacting with me using comments are available here.
If you have questions or suggestions related to my behavior, please file an issue against the gh-ci-bot repository.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical issue in the workspace migration process where improper path validation on Windows could lead to recursive directory copying. By standardizing path separator usage and introducing case-insensitive checks, the fix ensures that destination paths are correctly validated against source paths regardless of the host operating system.

Highlights

  • Path Validation Logic: Replaced hardcoded forward-slash path checking with a robust isNestedOrEqualWorkspacePath utility that utilizes path.sep to correctly handle cross-platform path separators.
  • Case-Insensitive Guard: Added case-insensitive path comparison for Windows and macOS environments to prevent potential recursive copy loops.
  • Regression Testing: Introduced a new test suite in workspace-init.test.ts to verify nested path detection across different operating systems.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the isNestedOrEqualWorkspacePath helper function to check if a target workspace path is nested within or equal to the current workspace path, accounting for platform-specific path separators and case-sensitivity. It also adds comprehensive unit tests. The review feedback identifies a critical bug where root directories (such as / or C:\) are not handled correctly, potentially causing recursive copy loops. To resolve this, the reviewer suggests refactoring the comparison logic using path.relative and path.isAbsolute and adding a corresponding test case.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines 3 to +4
import { join, resolve, sep } from 'path';
import { sep as winSep } from 'node:path/win32';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

To support robust path comparison using path.relative and path.isAbsolute (including platform-specific fallbacks for Windows to support testing on non-Windows platforms), let's import relative and isAbsolute from both 'path' and 'node:path/win32'.

Suggested change
import { join, resolve, sep } from 'path';
import { sep as winSep } from 'node:path/win32';
import { join, resolve, sep, relative, isAbsolute } from 'path';
import { sep as winSep, relative as winRelative, isAbsolute as winIsAbsolute } from 'node:path/win32';

Comment on lines +13 to +19
export function isNestedOrEqualWorkspacePath(resolvedOld: string, resolvedNew: string): boolean {
const caseInsensitive = process.platform === 'win32' || process.platform === 'darwin';
const normOld = caseInsensitive ? resolvedOld.toLowerCase() : resolvedOld;
const normNew = caseInsensitive ? resolvedNew.toLowerCase() : resolvedNew;
const pathSep = process.platform === 'win32' ? winSep : sep;
return normNew === normOld || normNew.startsWith(normOld + pathSep);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current implementation of isNestedOrEqualWorkspacePath has a bug when the old workspace path is the root directory (e.g., / on Unix or C:\ on Windows).

Specifically, normOld + pathSep evaluates to // or C:\\. Since normNew (e.g., /workspace or C:\workspace) only has a single separator, normNew.startsWith(normOld + pathSep) evaluates to false. This allows a nested workspace migration from the root directory, which could trigger a recursive copy loop.

Using path.relative and path.isAbsolute is much more robust and automatically handles trailing separators, root directories, and other path normalization edge cases.

Suggested change
export function isNestedOrEqualWorkspacePath(resolvedOld: string, resolvedNew: string): boolean {
const caseInsensitive = process.platform === 'win32' || process.platform === 'darwin';
const normOld = caseInsensitive ? resolvedOld.toLowerCase() : resolvedOld;
const normNew = caseInsensitive ? resolvedNew.toLowerCase() : resolvedNew;
const pathSep = process.platform === 'win32' ? winSep : sep;
return normNew === normOld || normNew.startsWith(normOld + pathSep);
}
export function isNestedOrEqualWorkspacePath(resolvedOld: string, resolvedNew: string): boolean {
const caseInsensitive = process.platform === 'win32' || process.platform === 'darwin';
const normOld = caseInsensitive ? resolvedOld.toLowerCase() : resolvedOld;
const normNew = caseInsensitive ? resolvedNew.toLowerCase() : resolvedNew;
const rel = process.platform === 'win32' ? winRelative(normOld, normNew) : relative(normOld, normNew);
const abs = process.platform === 'win32' ? winIsAbsolute(rel) : isAbsolute(rel);
return !rel.startsWith('..') && !abs;
}

Comment on lines +89 to +90
});
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Let's add a test case to verify that root directories are handled correctly and do not allow nested migrations.

Suggested change
});
});
});
it('handles root directory correctly', () => {
expect(isNestedOrEqualWorkspacePath('/', '/workspace')).toBe(true);
});
});

@advancedresearcharray

Copy link
Copy Markdown
Contributor Author

All checks have been addressed and CI is green. This PR is ready for merge.

@advancedresearcharray

Copy link
Copy Markdown
Contributor Author

CI is green, no review comments. Ready for merge.

@advancedresearcharray

Copy link
Copy Markdown
Contributor Author

PR is ready for merge 🚀

@advancedresearcharray

Copy link
Copy Markdown
Contributor Author

The CI is green and there are no review comments. This PR is ready for merge.

@advancedresearcharray

Copy link
Copy Markdown
Contributor Author

PR is ready for merge. CI is green and there are no outstanding review comments.

@advancedresearcharray

Copy link
Copy Markdown
Contributor Author

Looks good, ready for merge!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] migrateWorkspace path check uses hardcoded '/' separator, bypassed on Windows

1 participant