fix(test): avoid scanning publishable plugin packages

This commit is contained in:
Vincent Koc
2026-05-16 14:07:43 +08:00
parent 306ca4d3eb
commit 5d4166a368
@@ -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>();