Plugins: require explicit trust for workspace-discovered plugins (#44174)

* Plugins: disable implicit workspace plugin auto-load

* Tests: cover workspace plugin trust gating

* Changelog: note workspace plugin trust hardening

* Plugins: keep workspace trust gate ahead of memory slot defaults

* Tests: cover workspace memory-slot trust bypass
This commit is contained in:
Vincent Koc
2026-03-12 12:12:41 -04:00
committed by GitHub
parent 0a8fa0e001
commit 3e28e10c2f
4 changed files with 110 additions and 1 deletions

View File

@@ -1449,6 +1449,62 @@ describe("loadOpenClawPlugins", () => {
).toBe(true);
});
it("does not auto-load workspace-discovered plugins unless explicitly trusted", () => {
useNoBundledPlugins();
const workspaceDir = makeTempDir();
const workspaceExtDir = path.join(workspaceDir, ".openclaw", "extensions", "workspace-helper");
fs.mkdirSync(workspaceExtDir, { recursive: true });
writePlugin({
id: "workspace-helper",
body: `module.exports = { id: "workspace-helper", register() {} };`,
dir: workspaceExtDir,
filename: "index.cjs",
});
const registry = loadOpenClawPlugins({
cache: false,
workspaceDir,
config: {
plugins: {
enabled: true,
},
},
});
const workspacePlugin = registry.plugins.find((entry) => entry.id === "workspace-helper");
expect(workspacePlugin?.origin).toBe("workspace");
expect(workspacePlugin?.status).toBe("disabled");
expect(workspacePlugin?.error).toContain("workspace plugin (disabled by default)");
});
it("loads workspace-discovered plugins when plugins.allow explicitly trusts them", () => {
useNoBundledPlugins();
const workspaceDir = makeTempDir();
const workspaceExtDir = path.join(workspaceDir, ".openclaw", "extensions", "workspace-helper");
fs.mkdirSync(workspaceExtDir, { recursive: true });
writePlugin({
id: "workspace-helper",
body: `module.exports = { id: "workspace-helper", register() {} };`,
dir: workspaceExtDir,
filename: "index.cjs",
});
const registry = loadOpenClawPlugins({
cache: false,
workspaceDir,
config: {
plugins: {
enabled: true,
allow: ["workspace-helper"],
},
},
});
const workspacePlugin = registry.plugins.find((entry) => entry.id === "workspace-helper");
expect(workspacePlugin?.origin).toBe("workspace");
expect(workspacePlugin?.status).toBe("loaded");
});
it("warns when loaded non-bundled plugin has no install/load-path provenance", () => {
useNoBundledPlugins();
const stateDir = makeTempDir();