Skip to content

Commit 8cfb48d

Browse files
committed
fix(uninstall): guard cleanup ancestors of cwd
1 parent b154e83 commit 8cfb48d

2 files changed

Lines changed: 24 additions & 1 deletion

File tree

src/commands/cleanup-utils.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,4 +213,27 @@ describe("cleanup path removals", () => {
213213
expect(runtime.error.mock.calls[0][0]).toMatch(/Refusing to remove unsafe path/);
214214
expect(runtime.log.mock.calls.length).toBe(0);
215215
});
216+
217+
it("refuses to remove a directory containing the current working directory", async () => {
218+
const runtime = createRuntimeMock();
219+
const tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-cleanup-cwd-"));
220+
const nestedCwd = path.join(tmpRoot, "nested");
221+
const cwdSpy = vi.spyOn(process, "cwd");
222+
223+
try {
224+
await fs.mkdir(nestedCwd);
225+
cwdSpy.mockReturnValue(nestedCwd);
226+
227+
const result = await removePath(tmpRoot, runtime, { dryRun: true });
228+
229+
expect(result.ok).toBe(false);
230+
expect(result.skipped).toBeUndefined();
231+
expect(runtime.error.mock.calls.length).toBe(1);
232+
expect(runtime.error.mock.calls[0][0]).toMatch(/Refusing to remove unsafe path/);
233+
expect(runtime.log.mock.calls.length).toBe(0);
234+
} finally {
235+
cwdSpy.mockRestore();
236+
await fs.rm(tmpRoot, { recursive: true, force: true });
237+
}
238+
});
216239
});

src/commands/cleanup-utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ function isUnsafeRemovalTarget(target: string): boolean {
8383
if (home && resolved === path.resolve(home)) {
8484
return true;
8585
}
86-
if (resolved === path.resolve(process.cwd())) {
86+
if (isPathWithin(path.resolve(process.cwd()), resolved)) {
8787
return true;
8888
}
8989
return false;

0 commit comments

Comments
 (0)