mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 13:00:44 +00:00
fix(postinstall): reject dist symlink escapes
This commit is contained in:
@@ -5,6 +5,7 @@ import { withTempDir } from "../test-helpers/temp-dir.js";
|
||||
import {
|
||||
collectPackageDistInventoryErrors,
|
||||
PACKAGE_DIST_INVENTORY_RELATIVE_PATH,
|
||||
collectPackageDistInventory,
|
||||
writePackageDistInventory,
|
||||
} from "./package-dist-inventory.js";
|
||||
|
||||
@@ -63,4 +64,17 @@ describe("package dist inventory", () => {
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects symlinked dist entries", async () => {
|
||||
await withTempDir({ prefix: "openclaw-dist-inventory-symlink-" }, async (packageRoot) => {
|
||||
const distDir = path.join(packageRoot, "dist");
|
||||
await fs.mkdir(distDir, { recursive: true });
|
||||
await fs.writeFile(path.join(packageRoot, "escape.js"), "export {};\n", "utf8");
|
||||
await fs.symlink(path.join(packageRoot, "escape.js"), path.join(distDir, "entry.js"));
|
||||
|
||||
await expect(collectPackageDistInventory(packageRoot)).rejects.toThrow(
|
||||
"Unsafe package dist path: dist/entry.js",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -34,15 +34,24 @@ function isPackagedDistPath(relativePath: string): boolean {
|
||||
}
|
||||
async function collectRelativeFiles(rootDir: string, baseDir: string): Promise<string[]> {
|
||||
try {
|
||||
const rootStats = await fs.lstat(rootDir);
|
||||
if (!rootStats.isDirectory() || rootStats.isSymbolicLink()) {
|
||||
throw new Error(
|
||||
`Unsafe package dist path: ${normalizeRelativePath(path.relative(baseDir, rootDir))}`,
|
||||
);
|
||||
}
|
||||
const entries = await fs.readdir(rootDir, { withFileTypes: true });
|
||||
const files = await Promise.all(
|
||||
entries.map(async (entry) => {
|
||||
const entryPath = path.join(rootDir, entry.name);
|
||||
const relativePath = normalizeRelativePath(path.relative(baseDir, entryPath));
|
||||
if (entry.isSymbolicLink()) {
|
||||
throw new Error(`Unsafe package dist path: ${relativePath}`);
|
||||
}
|
||||
if (entry.isDirectory()) {
|
||||
return await collectRelativeFiles(entryPath, baseDir);
|
||||
}
|
||||
if (entry.isFile() || entry.isSymbolicLink()) {
|
||||
const relativePath = normalizeRelativePath(path.relative(baseDir, entryPath));
|
||||
if (entry.isFile()) {
|
||||
return isPackagedDistPath(relativePath) ? [relativePath] : [];
|
||||
}
|
||||
return [];
|
||||
|
||||
Reference in New Issue
Block a user