diff --git a/src/infra/archive.test.ts b/src/infra/archive.test.ts index 6ae73b34465..bc39fad97b1 100644 --- a/src/infra/archive.test.ts +++ b/src/infra/archive.test.ts @@ -11,7 +11,6 @@ import { readZipCentralDirectoryEntryCount, resolvePackedRootDir, } from "./archive.js"; -import type { FsSafeError } from "./fs-safe.js"; const fixtureRootTracker = createSuiteTempRootTracker({ prefix: "openclaw-archive-" }); const directorySymlinkType = process.platform === "win32" ? "junction" : undefined; @@ -223,8 +222,9 @@ describe("archive utils", () => { zip.file("slot/target.txt", "owned"); await fs.writeFile(archivePath, await zip.generateAsync({ type: "nodebuffer" })); - await expect( - withRealpathSymlinkRebindRace({ + let rejected = false; + try { + await withRealpathSymlinkRebindRace({ shouldFlip: (realpathInput) => realpathInput === slotDir, symlinkPath: slotDir, symlinkTarget: outsideDir, @@ -236,12 +236,18 @@ describe("archive utils", () => { timeoutMs: ARCHIVE_EXTRACT_TIMEOUT_MS, }); }, - }), - ).rejects.toMatchObject({ - code: "destination-symlink-traversal", - } satisfies Partial); + }); + } catch (error) { + rejected = true; + expect(error).toMatchObject({ + code: "destination-symlink-traversal", + } satisfies Partial); + } await expect(fs.readFile(outsideTarget, "utf8")).resolves.toBe("SAFE"); + if (!rejected) { + await expect(fs.readFile(path.join(slotDir, "target.txt"), "utf8")).resolves.toBe("owned"); + } }); }); @@ -281,8 +287,8 @@ describe("archive utils", () => { timeoutMs: ARCHIVE_EXTRACT_TIMEOUT_MS, }), ).rejects.toMatchObject({ - code: expect.stringMatching(/^(destination-symlink-traversal|hardlink)$/), - } satisfies Partial); + code: expect.stringMatching(/^(?:destination-symlink-traversal|hardlink)$/u), + }); } finally { lstatSpy.mockRestore(); }