mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 04:47:03 -06:00
fix(test): avoid scanning publishable plugin packages
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { execFile } from "node:child_process";
|
||||
import { copyFileSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync } from "node:fs";
|
||||
import { execFile, spawnSync } from "node:child_process";
|
||||
import fs, { copyFileSync, mkdirSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { dirname, join, relative, resolve, sep } from "node:path";
|
||||
import { promisify } from "node:util";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { isScannable, scanDirectoryWithSummary } from "../security/skill-scanner.js";
|
||||
|
||||
type NpmPackFile = {
|
||||
@@ -130,11 +130,73 @@ function stageScannerRelevantPackedFiles(
|
||||
return stageDir;
|
||||
}
|
||||
|
||||
function collectPublishablePluginPackages(): PublishablePluginPackage[] {
|
||||
return readdirSync("extensions", { withFileTypes: true })
|
||||
function listPublishablePluginPackageDirs(): string[] {
|
||||
const externalDirs = listExternalPluginPackageDirs();
|
||||
if (externalDirs) {
|
||||
return externalDirs;
|
||||
}
|
||||
return fs
|
||||
.readdirSync("extensions", { withFileTypes: true })
|
||||
.filter((entry) => entry.isDirectory())
|
||||
.flatMap((entry) => {
|
||||
const packageDir = join("extensions", entry.name);
|
||||
.map((entry) => join("extensions", entry.name))
|
||||
.toSorted();
|
||||
}
|
||||
|
||||
function listExternalPluginPackageDirs(): string[] | null {
|
||||
const packageFiles = listGitExtensionPackageFiles() ?? listFindExtensionPackageFiles();
|
||||
if (!packageFiles) {
|
||||
return null;
|
||||
}
|
||||
return packageFiles
|
||||
.flatMap((file) => {
|
||||
const match = /^extensions\/([^/]+)\/package\.json$/u.exec(file);
|
||||
return match?.[1] ? [join("extensions", match[1])] : [];
|
||||
})
|
||||
.toSorted();
|
||||
}
|
||||
|
||||
function listGitExtensionPackageFiles(): string[] | null {
|
||||
const result = spawnSync("git", ["ls-files", "--", "extensions/*/package.json"], {
|
||||
cwd: process.cwd(),
|
||||
encoding: "utf8",
|
||||
maxBuffer: 1024 * 1024,
|
||||
stdio: ["ignore", "pipe", "ignore"],
|
||||
});
|
||||
if (result.status !== 0) {
|
||||
return null;
|
||||
}
|
||||
return result.stdout
|
||||
.split("\n")
|
||||
.map((line) => line.trim())
|
||||
.filter((line) => line.length > 0)
|
||||
.toSorted();
|
||||
}
|
||||
|
||||
function listFindExtensionPackageFiles(): string[] | null {
|
||||
const result = spawnSync(
|
||||
"find",
|
||||
[resolve("extensions"), "-maxdepth", "2", "-type", "f", "-name", "package.json"],
|
||||
{
|
||||
cwd: process.cwd(),
|
||||
encoding: "utf8",
|
||||
maxBuffer: 1024 * 1024,
|
||||
stdio: ["ignore", "pipe", "ignore"],
|
||||
},
|
||||
);
|
||||
if (result.status !== 0) {
|
||||
return null;
|
||||
}
|
||||
return result.stdout
|
||||
.split("\n")
|
||||
.map((line) => line.trim())
|
||||
.filter((line) => line.length > 0)
|
||||
.map((file) => relative(process.cwd(), file).split(sep).join("/"))
|
||||
.toSorted();
|
||||
}
|
||||
|
||||
function collectPublishablePluginPackages(): PublishablePluginPackage[] {
|
||||
return listPublishablePluginPackageDirs()
|
||||
.flatMap((packageDir) => {
|
||||
const packageJsonPath = join(packageDir, "package.json");
|
||||
let packageJson: {
|
||||
name?: unknown;
|
||||
@@ -231,6 +293,21 @@ async function scanPublishablePluginPackage(plugin: PublishablePluginPackage): P
|
||||
}
|
||||
|
||||
describe("publishable plugin npm package install security scan", () => {
|
||||
it("lists publishable plugin packages without scanning extension directories in-process", () => {
|
||||
const readDir = vi.spyOn(fs, "readdirSync");
|
||||
try {
|
||||
const packages = collectPublishablePluginPackages();
|
||||
|
||||
expect(packages.length).toBeGreaterThan(0);
|
||||
expect(
|
||||
packages.every((plugin) => plugin.packageDir.split(sep).join("/").startsWith("extensions/")),
|
||||
).toBe(true);
|
||||
expect(readDir).not.toHaveBeenCalled();
|
||||
} finally {
|
||||
readDir.mockRestore();
|
||||
}
|
||||
});
|
||||
|
||||
it("keeps npm-published plugin files clear of unexpected critical hits", async () => {
|
||||
const unexpectedCriticalFindings: string[] = [];
|
||||
const reviewedCriticalFindings = new Set<string>();
|
||||
|
||||
Reference in New Issue
Block a user