fix(plugins): trust catalog package installs

This commit is contained in:
Vincent Koc
2026-05-04 11:30:26 -07:00
parent 9dc38f37ea
commit daefb5e341
3 changed files with 39 additions and 7 deletions

View File

@@ -2,7 +2,7 @@ import { describe, expect, it } from "vitest";
import { getChannelPluginCatalogEntry } from "./catalog.js";
describe("channel plugin catalog", () => {
it("keeps third-party official channel ids mapped to their published plugin ids", () => {
it("keeps third-party channel ids mapped with catalog install trust", () => {
const options = {
workspaceDir: "/tmp/openclaw-channel-catalog-empty-workspace",
env: {},

View File

@@ -734,7 +734,7 @@ describe("plugins cli install", () => {
expect(writeConfigFile).toHaveBeenCalledWith(enabledCfg);
});
it("passes official external catalog integrity to npm installs", async () => {
it("passes third-party external catalog integrity with catalog install trust", async () => {
const cfg = createEmptyPluginConfig();
const enabledCfg = createEnabledPluginConfig("wecom-openclaw-plugin");
loadConfig.mockReturnValue(cfg);
@@ -796,7 +796,7 @@ describe("plugins cli install", () => {
},
);
it("passes official external catalog integrity to hook-pack fallback", async () => {
it("passes third-party external catalog integrity to hook-pack fallback", async () => {
loadConfig.mockReturnValue(createEmptyPluginConfig());
findBundledPluginSourceMock.mockReturnValue(undefined);
installPluginFromNpmSpec.mockResolvedValue({
@@ -992,6 +992,38 @@ describe("plugins cli install", () => {
expect(installPluginFromClawHub).not.toHaveBeenCalled();
});
it("marks catalog npm package installs with alternate selectors as trusted", async () => {
const cfg = createEmptyPluginConfig();
const enabledCfg = createEnabledPluginConfig("wecom-openclaw-plugin");
loadConfig.mockReturnValue(cfg);
installPluginFromNpmSpec.mockResolvedValue(
createNpmPluginInstallResult("wecom-openclaw-plugin"),
);
enablePluginInConfig.mockReturnValue({ config: enabledCfg });
recordPluginInstall.mockReturnValue(enabledCfg);
applyExclusiveSlotSelection.mockReturnValue({
config: enabledCfg,
warnings: [],
});
await runPluginsCommand(["plugins", "install", "@wecom/wecom-openclaw-plugin@latest"]);
expect(installPluginFromNpmSpec).toHaveBeenCalledWith(
expect.objectContaining({
spec: "@wecom/wecom-openclaw-plugin@latest",
expectedPluginId: "wecom-openclaw-plugin",
trustedSourceLinkedOfficialInstall: true,
}),
);
expect(installPluginFromNpmSpec).toHaveBeenCalledWith(
expect.not.objectContaining({
expectedIntegrity: expect.any(String),
}),
);
expect(installPluginFromClawHub).not.toHaveBeenCalled();
});
it("passes the active profile extensions dir to npm installs", async () => {
const extensionsDir = useProfileExtensionsDir();
const cfg = createEmptyPluginConfig();

View File

@@ -64,7 +64,7 @@ function resolveInstallSafetyOverrides(overrides: InstallSafetyOverrides): Insta
};
}
function findTrustedOfficialExternalPackageInstall(packageName: string):
function findTrustedCatalogPackageInstall(packageName: string):
| {
pluginId: string;
npmSpec?: string;
@@ -72,7 +72,7 @@ function findTrustedOfficialExternalPackageInstall(packageName: string):
}
| undefined {
const entry = getOfficialExternalPluginCatalogEntryForPackage(packageName);
if (entry?.source !== "official") {
if (!entry) {
return undefined;
}
const pluginId = resolveOfficialExternalPluginId(entry);
@@ -723,7 +723,7 @@ export async function runPluginInstallCommand(params: {
}
const officialNpmTrust = resolveOfficialExternalNpmPackageTrust({
npmSpec: npmPrefixSpec,
findOfficialExternalPackage: findTrustedOfficialExternalPackageInstall,
findOfficialExternalPackage: findTrustedCatalogPackageInstall,
});
const npmPrefixResult = await tryInstallPluginOrHookPackFromNpmSpec({
snapshot,
@@ -870,7 +870,7 @@ export async function runPluginInstallCommand(params: {
const officialNpmTrust = resolveOfficialExternalNpmPackageTrust({
npmSpec: raw,
findOfficialExternalPackage: findTrustedOfficialExternalPackageInstall,
findOfficialExternalPackage: findTrustedCatalogPackageInstall,
});
const npmResult = await tryInstallPluginOrHookPackFromNpmSpec({
snapshot,