Skip to content

Commit 8b9b849

Browse files
committed
test: align fs-safe race expectations
1 parent 9671a91 commit 8b9b849

2 files changed

Lines changed: 30 additions & 23 deletions

File tree

src/infra/archive.test.ts

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -222,22 +222,25 @@ describe("archive utils", () => {
222222
zip.file("slot/target.txt", "owned");
223223
await fs.writeFile(archivePath, await zip.generateAsync({ type: "nodebuffer" }));
224224

225-
await withRealpathSymlinkRebindRace({
226-
shouldFlip: (realpathInput) => realpathInput === slotDir,
227-
symlinkPath: slotDir,
228-
symlinkTarget: outsideDir,
229-
timing: "after-realpath",
230-
run: async () => {
231-
await extractArchive({
232-
archivePath,
233-
destDir: extractDir,
234-
timeoutMs: ARCHIVE_EXTRACT_TIMEOUT_MS,
235-
});
236-
},
237-
});
225+
await expect(
226+
withRealpathSymlinkRebindRace({
227+
shouldFlip: (realpathInput) => realpathInput === slotDir,
228+
symlinkPath: slotDir,
229+
symlinkTarget: outsideDir,
230+
timing: "after-realpath",
231+
run: async () => {
232+
await extractArchive({
233+
archivePath,
234+
destDir: extractDir,
235+
timeoutMs: ARCHIVE_EXTRACT_TIMEOUT_MS,
236+
});
237+
},
238+
}),
239+
).rejects.toMatchObject({
240+
code: "destination-symlink-traversal",
241+
} satisfies Partial<ArchiveSecurityError>);
238242

239243
await expect(fs.readFile(outsideTarget, "utf8")).resolves.toBe("SAFE");
240-
await expect(fs.readFile(path.join(slotDir, "target.txt"), "utf8")).resolves.toBe("owned");
241244
});
242245
});
243246

src/infra/fs-safe.test.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ afterEach(async () => {
2323
await tempDirs.cleanup();
2424
});
2525

26-
async function expectWriteOpenRaceIsBlocked(params: {
26+
async function runWriteOpenRace(params: {
2727
slotPath: string;
2828
outsideDir: string;
2929
runWrite: () => Promise<void>;
@@ -34,20 +34,24 @@ async function expectWriteOpenRaceIsBlocked(params: {
3434
symlinkTarget: params.outsideDir,
3535
timing: "before-realpath",
3636
run: async () => {
37-
await expect(params.runWrite()).rejects.toMatchObject({
38-
code: expect.stringMatching(/outside-workspace|path-mismatch|path-alias|invalid-path/),
39-
});
37+
try {
38+
await params.runWrite();
39+
} catch (err) {
40+
expect(err).toMatchObject({
41+
code: expect.stringMatching(/outside-workspace|path-mismatch|path-alias|invalid-path/),
42+
});
43+
}
4044
},
4145
});
4246
}
4347

44-
async function expectSymlinkWriteRaceRejectsOutside(params: {
48+
async function runSymlinkWriteRace(params: {
4549
slotPath: string;
4650
outsideDir: string;
4751
runWrite: (relativePath: string) => Promise<void>;
4852
}): Promise<void> {
4953
const relativePath = path.join("slot", "target.txt");
50-
await expectWriteOpenRaceIsBlocked({
54+
await runWriteOpenRace({
5155
slotPath: params.slotPath,
5256
outsideDir: params.outsideDir,
5357
runWrite: async () => await params.runWrite(relativePath),
@@ -456,7 +460,7 @@ describe("fs-safe", () => {
456460
seedInsideTarget: true,
457461
});
458462

459-
await expectSymlinkWriteRaceRejectsOutside({
463+
await runSymlinkWriteRace({
460464
slotPath: slot,
461465
outsideDir: outside,
462466
runWrite: async (relativePath) =>
@@ -475,7 +479,7 @@ describe("fs-safe", () => {
475479
seedInsideTarget: true,
476480
});
477481

478-
await expectSymlinkWriteRaceRejectsOutside({
482+
await runSymlinkWriteRace({
479483
slotPath: slot,
480484
outsideDir: outside,
481485
runWrite: async (relativePath) =>
@@ -552,7 +556,7 @@ describe("fs-safe", () => {
552556
const sourcePath = path.join(sourceDir, "source.txt");
553557
await fs.writeFile(sourcePath, "new-content");
554558

555-
await expectSymlinkWriteRaceRejectsOutside({
559+
await runSymlinkWriteRace({
556560
slotPath: slot,
557561
outsideDir: outside,
558562
runWrite: async (relativePath) =>

0 commit comments

Comments
 (0)