




















@@ -55,8 +55,23 @@ async function createDirectorySymlink(targetDir: string, linkPath: string) {
5555await fs.symlink(targetDir, linkPath, directorySymlinkType);
5656}
575758+async function expectRejectedCode(promise: Promise<unknown>, expected: string | RegExp) {
59+try {
60+await promise;
61+} catch (error) {
62+const code = (error as Partial<ArchiveSecurityError>).code;
63+if (typeof expected === "string") {
64+expect(code).toBe(expected);
65+return;
66+}
67+expect(String(code)).toMatch(expected);
68+return;
69+}
70+throw new Error("expected promise to reject");
71+}
72+5873async function expectPathMissing(filePath: string) {
59-await expect(fs.stat(filePath)).rejects.toMatchObject({ code: "ENOENT" });
74+await expectRejectedCode(fs.stat(filePath), "ENOENT");
6075}
61766277async function expectExtractedSizeBudgetExceeded(params: {
@@ -148,15 +163,14 @@ describe("archive utils", () => {
148163await fs.rm(extractDir, { recursive: true, force: true });
149164await createDirectorySymlink(realExtractDir, extractDir);
150165151-await expect(
166+await expectRejectedCode(
152167extractArchive({
153168 archivePath,
154169destDir: extractDir,
155170timeoutMs: ARCHIVE_EXTRACT_TIMEOUT_MS,
156171}),
157-).rejects.toMatchObject({
158-code: "destination-symlink",
159-} satisfies Partial<ArchiveSecurityError>);
172+"destination-symlink",
173+);
160174161175await expectPathMissing(path.join(realExtractDir, "package", "hello.txt"));
162176});
@@ -189,15 +203,14 @@ describe("archive utils", () => {
189203zip.file("escape/pwn.txt", "owned");
190204await fs.writeFile(archivePath, await zip.generateAsync({ type: "nodebuffer" }));
191205192-await expect(
206+await expectRejectedCode(
193207extractArchive({
194208 archivePath,
195209destDir: extractDir,
196210timeoutMs: ARCHIVE_EXTRACT_TIMEOUT_MS,
197211}),
198-).rejects.toMatchObject({
199-code: "destination-symlink-traversal",
200-} satisfies Partial<ArchiveSecurityError>);
212+"destination-symlink-traversal",
213+);
201214202215const outsideFile = path.join(outsideDir, "pwn.txt");
203216const outsideExists = await fs
@@ -239,9 +252,8 @@ describe("archive utils", () => {
239252});
240253} catch (error) {
241254rejected = true;
242-expect(error).toMatchObject({
243-code: expect.stringMatching(/destination-symlink-traversal|not-file/),
244-} satisfies Partial<ArchiveSecurityError>);
255+const code = (error as Partial<ArchiveSecurityError>).code;
256+expect(String(code)).toMatch(/destination-symlink-traversal|not-file/);
245257}
246258247259await expect(fs.readFile(outsideTarget, "utf8")).resolves.toBe("SAFE");
@@ -280,21 +292,20 @@ describe("archive utils", () => {
280292});
281293282294try {
283-await expect(
295+await expectRejectedCode(
284296extractArchive({
285297 archivePath,
286298destDir: extractDir,
287299timeoutMs: ARCHIVE_EXTRACT_TIMEOUT_MS,
288300}),
289-).rejects.toMatchObject({
290-code: expect.stringMatching(/^(?:destination-symlink-traversal|hardlink)$/u),
291-});
301+/^(?:destination-symlink-traversal|hardlink)$/u,
302+);
292303} finally {
293304lstatSpy.mockRestore();
294305}
295306296307await expect(fs.readFile(outsideAlias, "utf8")).resolves.toBe("");
297-await expect(fs.stat(extractedPath)).rejects.toMatchObject({ code: "ENOENT" });
308+await expectPathMissing(extractedPath);
298309});
299310},
300311);
@@ -327,15 +338,14 @@ describe("archive utils", () => {
327338await createDirectorySymlink(outsideDir, path.join(extractDir, "escape"));
328339await tar.c({ cwd: archiveRoot, file: archivePath }, ["escape"]);
329340330-await expect(
341+await expectRejectedCode(
331342extractArchive({
332343 archivePath,
333344destDir: extractDir,
334345timeoutMs: ARCHIVE_EXTRACT_TIMEOUT_MS,
335346}),
336-).rejects.toMatchObject({
337-code: "destination-symlink-traversal",
338-} satisfies Partial<ArchiveSecurityError>);
347+"destination-symlink-traversal",
348+);
339349340350await expectPathMissing(path.join(outsideDir, "pwn.txt"));
341351});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。