























@@ -20,6 +20,7 @@ const tempDirs = createTrackedTempDirs();
20202121afterEach(async () => {
2222__setFsSafeTestHooksForTest(undefined);
23+vi.restoreAllMocks();
2324vi.unstubAllEnvs();
2425await tempDirs.cleanup();
2526});
@@ -182,21 +183,57 @@ describe("fs-safe", () => {
182183await fs.writeFile(originalPath, "inside");
183184await fs.writeFile(outsidePath, "outside");
184185186+const originalRealpath = fs.realpath.bind(fs);
187+const realpathSpy = vi.spyOn(fs, "realpath");
188+realpathSpy.mockImplementation(async (target) => {
189+if (typeof target === "string" && target.startsWith("/dev/fd/")) {
190+return movedPath;
191+}
192+return await originalRealpath(target);
193+});
194+185195const handle = await fs.open(originalPath, "r");
186196try {
187197await fs.rename(originalPath, movedPath);
188198await fs.symlink(outsidePath, originalPath);
189199190200const resolved = await resolveOpenedFileRealPathForHandle(handle, originalPath);
191201192-await expect(fs.realpath(movedPath)).resolves.toBe(resolved);
202+expect(resolved).toBe(movedPath);
193203await expect(handle.readFile({ encoding: "utf8" })).resolves.toBe("inside");
194204} finally {
195205await handle.close().catch(() => {});
196206}
197207},
198208);
199209210+it.runIf(process.platform !== "win32")(
211+"falls back to the io path when /dev/fd realpath does not resolve to the opened file",
212+async () => {
213+const root = await tempDirs.make("openclaw-fs-safe-root-");
214+const filePath = path.join(root, "inside.txt");
215+await fs.writeFile(filePath, "inside");
216+217+const originalRealpath = fs.realpath.bind(fs);
218+const realpathSpy = vi.spyOn(fs, "realpath");
219+realpathSpy.mockImplementation(async (target) => {
220+if (typeof target === "string" && target.startsWith("/dev/fd/")) {
221+return "/dev/fd/inside.txt";
222+}
223+return await originalRealpath(target);
224+});
225+226+const handle = await fs.open(filePath, "r");
227+try {
228+await expect(resolveOpenedFileRealPathForHandle(handle, filePath)).resolves.toBe(
229+await originalRealpath(filePath),
230+);
231+} finally {
232+await handle.close().catch(() => {});
233+}
234+},
235+);
236+200237it("blocks traversal outside root", async () => {
201238const root = await tempDirs.make("openclaw-fs-safe-root-");
202239const outside = await tempDirs.make("openclaw-fs-safe-outside-");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。