From d1ab308f5c770f13eefe2e6769c41729438e2a92 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Fri, 19 Jun 2026 10:44:18 +0800 Subject: [PATCH] refactor(infra): trim dead archive facade exports --- src/infra/archive-path.test.ts | 119 +-------------------------------- src/infra/archive-path.ts | 4 -- src/infra/archive.ts | 2 - 3 files changed, 2 insertions(+), 123 deletions(-) diff --git a/src/infra/archive-path.test.ts b/src/infra/archive-path.test.ts index 4bf82ceca833..77838a1159ea 100644 --- a/src/infra/archive-path.test.ts +++ b/src/infra/archive-path.test.ts @@ -1,17 +1,6 @@ -// Covers archive entry path normalization and traversal rejection. -import path from "node:path"; +// Covers the archive-path facade used by runtime path classification. import { describe, expect, it } from "vitest"; -import { - isWindowsDrivePath, - normalizeArchiveEntryPath, - resolveArchiveOutputPath, - stripArchivePath, - validateArchiveEntryPath, -} from "./archive-path.js"; - -function expectArchivePathError(run: () => void, message: string) { - expect(run).toThrow(message); -} +import { isWindowsDrivePath } from "./archive-path.js"; describe("archive path helpers", () => { it.each([ @@ -22,108 +11,4 @@ describe("archive path helpers", () => { ])("detects Windows drive paths for %j", ({ value, expected }) => { expect(isWindowsDrivePath(value)).toBe(expected); }); - - it.each([ - { raw: "dir\\file.txt", expected: "dir/file.txt" }, - { raw: "dir/file.txt", expected: "dir/file.txt" }, - ])("normalizes archive separators for %j", ({ raw, expected }) => { - expect(normalizeArchiveEntryPath(raw)).toBe(expected); - }); - - it.each(["", ".", "./"])("accepts empty-like entry paths: %j", (entryPath) => { - expect(validateArchiveEntryPath(entryPath)).toBeUndefined(); - }); - - it.each([ - { - name: "uses custom escape labels in traversal errors", - entryPath: "../escape.txt", - message: "archive entry escapes targetDir: ../escape.txt", - }, - { - name: "rejects Windows drive paths", - entryPath: "C:\\temp\\file.txt", - message: "archive entry uses a drive path: C:\\temp\\file.txt", - }, - { - name: "rejects absolute paths after normalization", - entryPath: "/tmp/file.txt", - message: "archive entry is absolute: /tmp/file.txt", - }, - { - name: "rejects double-slash absolute paths after normalization", - entryPath: "\\\\server\\share.txt", - message: "archive entry is absolute: \\\\server\\share.txt", - }, - ])("$name", ({ entryPath, message }) => { - expectArchivePathError( - () => - validateArchiveEntryPath(entryPath, { - escapeLabel: "targetDir", - }), - message, - ); - }); - - it.each([ - { entryPath: "a/../escape.txt", stripComponents: 1, expected: "../escape.txt" }, - { entryPath: "a//b/file.txt", stripComponents: 1, expected: "b/file.txt" }, - { entryPath: "./", stripComponents: 0, expected: null }, - { entryPath: "a", stripComponents: 3, expected: null }, - { entryPath: "dir\\sub\\file.txt", stripComponents: 1, expected: "sub/file.txt" }, - ])("strips archive paths for %j", ({ entryPath, stripComponents, expected }) => { - expect(stripArchivePath(entryPath, stripComponents)).toBe(expected); - }); - - it("preserves strip-induced traversal for follow-up validation", () => { - const stripped = stripArchivePath("a/../escape.txt", 1); - expect(stripped).toBe("../escape.txt"); - expectArchivePathError( - () => - validateArchiveEntryPath(stripped ?? "", { - escapeLabel: "targetDir", - }), - "archive entry escapes targetDir: ../escape.txt", - ); - }); - - const rootDir = path.join(path.sep, "tmp", "archive-root"); - - it.each([ - { - name: "keeps resolved output paths inside the root", - relPath: "sub/file.txt", - originalPath: "sub/file.txt", - expected: path.resolve(rootDir, "sub/file.txt"), - }, - { - name: "rejects output paths that escape the root", - relPath: "../escape.txt", - originalPath: "../escape.txt", - escapeLabel: "targetDir", - message: "archive entry escapes targetDir: ../escape.txt", - }, - ])("$name", ({ relPath, originalPath, escapeLabel, expected, message }) => { - if (message) { - expectArchivePathError( - () => - resolveArchiveOutputPath({ - rootDir, - relPath, - originalPath, - escapeLabel, - }), - message, - ); - return; - } - - expect( - resolveArchiveOutputPath({ - rootDir, - relPath, - originalPath, - }), - ).toBe(expected); - }); }); diff --git a/src/infra/archive-path.ts b/src/infra/archive-path.ts index 7ac79d38d113..cab6c8afd3c9 100644 --- a/src/infra/archive-path.ts +++ b/src/infra/archive-path.ts @@ -4,8 +4,4 @@ import "./fs-safe-defaults.js"; // Archive path facade kept in infra so callers share one traversal policy. export { isWindowsDrivePath, - normalizeArchiveEntryPath, - resolveArchiveOutputPath, - stripArchivePath, - validateArchiveEntryPath, } from "@openclaw/fs-safe/archive"; diff --git a/src/infra/archive.ts b/src/infra/archive.ts index 1a46e4693495..bbb6dc7b1ce3 100644 --- a/src/infra/archive.ts +++ b/src/infra/archive.ts @@ -10,13 +10,11 @@ export { DEFAULT_MAX_ENTRIES, DEFAULT_MAX_EXTRACTED_BYTES, DEFAULT_MAX_ENTRY_BYTES, - createArchiveSymlinkTraversalError, createTarEntryPreflightChecker, extractArchive, loadZipArchiveWithPreflight, mergeExtractedTreeIntoDestination, prepareArchiveDestinationDir, - prepareArchiveOutputPath, readZipCentralDirectoryEntryCount, resolveArchiveKind, resolvePackedRootDir,