Skip to content

Commit 66785f8

Browse files
committed
fix: address issue
1 parent cbb7313 commit 66785f8

3 files changed

Lines changed: 201 additions & 7 deletions

File tree

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
import fs from "node:fs";
2+
import path from "node:path";
3+
import { afterEach, describe, expect, it } from "vitest";
4+
import { withEnv } from "../test-utils/env.js";
5+
import { resetPluginLoaderTestStateForTest } from "./loader.test-fixtures.js";
6+
import { resolvePluginProviders } from "./providers.runtime.js";
7+
import {
8+
cleanupTrackedTempDirs,
9+
makeTrackedTempDir,
10+
mkdirSafeDir,
11+
} from "./test-helpers/fs-fixtures.js";
12+
13+
const tempDirs: string[] = [];
14+
15+
afterEach(() => {
16+
cleanupTrackedTempDirs(tempDirs);
17+
resetPluginLoaderTestStateForTest();
18+
});
19+
20+
function makeTempDir() {
21+
return makeTrackedTempDir("openclaw-provider-setup-trust", tempDirs);
22+
}
23+
24+
function writeJson(filePath: string, value: unknown) {
25+
fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf-8");
26+
}
27+
28+
function readMarkerLines(filePath: string): string[] {
29+
if (!fs.existsSync(filePath)) {
30+
return [];
31+
}
32+
return fs
33+
.readFileSync(filePath, "utf-8")
34+
.split("\n")
35+
.map((line) => line.trim())
36+
.filter(Boolean);
37+
}
38+
39+
function writeWorkspaceProviderPlugin(params: {
40+
workspaceDir: string;
41+
pluginId: string;
42+
providerId: string;
43+
markerDir: string;
44+
}) {
45+
const pluginDir = path.join(params.workspaceDir, ".openclaw", "extensions", params.pluginId);
46+
mkdirSafeDir(pluginDir);
47+
writeJson(path.join(pluginDir, "openclaw.plugin.json"), {
48+
id: params.pluginId,
49+
name: "Setup Trust Provider",
50+
description: "Test workspace provider plugin",
51+
configSchema: {
52+
type: "object",
53+
additionalProperties: false,
54+
properties: {},
55+
},
56+
providers: [params.providerId],
57+
});
58+
fs.writeFileSync(
59+
path.join(pluginDir, "index.cjs"),
60+
`const fs = require("node:fs");
61+
const path = require("node:path");
62+
63+
const markerDir = ${JSON.stringify(params.markerDir)};
64+
fs.mkdirSync(markerDir, { recursive: true });
65+
fs.appendFileSync(
66+
path.join(markerDir, "top-level.txt"),
67+
JSON.stringify({ event: "top-level", registrationMode: "module-import" }) + "\\n",
68+
);
69+
70+
module.exports = {
71+
id: ${JSON.stringify(params.pluginId)},
72+
register(api) {
73+
fs.appendFileSync(
74+
path.join(markerDir, "register.txt"),
75+
JSON.stringify({ event: "register", registrationMode: api.registrationMode }) + "\\n",
76+
);
77+
api.registerProvider({
78+
id: ${JSON.stringify(params.providerId)},
79+
label: "Setup Trust Provider",
80+
auth: [],
81+
});
82+
},
83+
};
84+
`,
85+
"utf-8",
86+
);
87+
}
88+
89+
describe("setup provider workspace trust", () => {
90+
it("does not import untrusted workspace provider plugins during default setup discovery", () => {
91+
const runRoot = makeTempDir();
92+
const workspaceDir = path.join(runRoot, "workspace");
93+
const stateDir = path.join(runRoot, "state");
94+
const markerDir = path.join(runRoot, "markers");
95+
mkdirSafeDir(workspaceDir);
96+
mkdirSafeDir(stateDir);
97+
mkdirSafeDir(markerDir);
98+
writeWorkspaceProviderPlugin({
99+
workspaceDir,
100+
pluginId: "setup-autoload-provider",
101+
providerId: "setup-autoload",
102+
markerDir,
103+
});
104+
105+
const env: NodeJS.ProcessEnv = {
106+
OPENCLAW_STATE_DIR: stateDir,
107+
OPENCLAW_DISABLE_BUNDLED_PLUGINS: "1",
108+
OPENCLAW_BUNDLED_PLUGINS_DIR: undefined,
109+
};
110+
111+
withEnv(env, () => {
112+
const providers = resolvePluginProviders({
113+
config: {
114+
plugins: {
115+
enabled: true,
116+
},
117+
},
118+
workspaceDir,
119+
env,
120+
mode: "setup",
121+
cache: false,
122+
onlyPluginIds: ["setup-autoload-provider"],
123+
});
124+
125+
expect(providers).toStrictEqual([]);
126+
});
127+
expect(readMarkerLines(path.join(markerDir, "top-level.txt"))).toStrictEqual([]);
128+
expect(readMarkerLines(path.join(markerDir, "register.txt"))).toStrictEqual([]);
129+
});
130+
131+
it("loads explicitly trusted workspace provider plugins during setup discovery", () => {
132+
const runRoot = makeTempDir();
133+
const workspaceDir = path.join(runRoot, "workspace");
134+
const stateDir = path.join(runRoot, "state");
135+
const markerDir = path.join(runRoot, "markers");
136+
mkdirSafeDir(workspaceDir);
137+
mkdirSafeDir(stateDir);
138+
mkdirSafeDir(markerDir);
139+
writeWorkspaceProviderPlugin({
140+
workspaceDir,
141+
pluginId: "setup-trusted-provider",
142+
providerId: "setup-trusted",
143+
markerDir,
144+
});
145+
146+
const env: NodeJS.ProcessEnv = {
147+
OPENCLAW_STATE_DIR: stateDir,
148+
OPENCLAW_DISABLE_BUNDLED_PLUGINS: "1",
149+
OPENCLAW_BUNDLED_PLUGINS_DIR: undefined,
150+
};
151+
152+
withEnv(env, () => {
153+
const providers = resolvePluginProviders({
154+
config: {
155+
plugins: {
156+
allow: ["setup-trusted-provider"],
157+
},
158+
},
159+
workspaceDir,
160+
env,
161+
mode: "setup",
162+
cache: false,
163+
onlyPluginIds: ["setup-trusted-provider"],
164+
});
165+
166+
expect(providers).toEqual([
167+
{
168+
id: "setup-trusted",
169+
label: "Setup Trust Provider",
170+
auth: [],
171+
pluginId: "setup-trusted-provider",
172+
},
173+
]);
174+
});
175+
expect(readMarkerLines(path.join(markerDir, "top-level.txt"))).toHaveLength(1);
176+
expect(readMarkerLines(path.join(markerDir, "register.txt"))).toHaveLength(1);
177+
});
178+
});

src/plugins/providers.test.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -928,7 +928,7 @@ describe("resolvePluginProviders", () => {
928928
});
929929
});
930930

931-
it("loads all discovered provider plugins in setup mode for explicit compat configs", () => {
931+
it("excludes untrusted workspace provider plugins from setup discovery by default", () => {
932932
resolvePluginProviders({
933933
config: {
934934
plugins: {
@@ -943,20 +943,36 @@ describe("resolvePluginProviders", () => {
943943
});
944944

945945
expectLastSetupRegistryLoad({
946-
onlyPluginIds: ["google", "kilocode", "moonshot", "workspace-provider"],
946+
onlyPluginIds: ["google", "kilocode", "moonshot"],
947947
});
948948
expectPluginConfigState(getLastSetupLoadedPluginConfig(), {
949-
allow: ["openrouter", "google", "kilocode", "moonshot", "workspace-provider"],
949+
allow: ["openrouter", "google", "kilocode", "moonshot"],
950950
entries: {
951951
google: { enabled: false },
952952
kilocode: { enabled: true },
953953
moonshot: { enabled: true },
954-
"workspace-provider": { enabled: true },
955954
},
956955
});
957956
});
958957

959-
it("excludes untrusted workspace provider plugins from setup discovery when requested", () => {
958+
it("loads explicitly included untrusted workspace provider plugins in setup discovery", () => {
959+
resolvePluginProviders({
960+
config: {
961+
plugins: {
962+
allow: ["openrouter"],
963+
bundledDiscovery: "compat",
964+
},
965+
},
966+
mode: "setup",
967+
includeUntrustedWorkspacePlugins: true,
968+
});
969+
970+
expectLastSetupRegistryLoad({
971+
onlyPluginIds: ["google", "kilocode", "moonshot", "workspace-provider"],
972+
});
973+
});
974+
975+
it("excludes untrusted workspace provider plugins from setup discovery when explicitly requested", () => {
960976
resolvePluginProviders({
961977
config: {
962978
plugins: {

src/plugins/providers.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ export function resolveDiscoveredProviderPluginIds(params: {
254254
}): string[] {
255255
const { registry, onlyPluginIdSet } = loadScopedProviderRegistry(params);
256256
const providerSurfacePluginIds = resolveProviderSurfacePluginIdSet({ ...params, registry });
257-
const shouldFilterUntrustedWorkspacePlugins = params.includeUntrustedWorkspacePlugins === false;
257+
const shouldFilterUntrustedWorkspacePlugins = params.includeUntrustedWorkspacePlugins !== true;
258258
const shouldFilterBundledByAllowlist = params.config?.plugins?.bundledDiscovery !== "compat";
259259
const normalizedConfig = normalizePluginsConfigWithRegistry(params.config?.plugins, registry);
260260
return listRegistryPluginIds(registry, (plugin) => {
@@ -315,7 +315,7 @@ export function resolveDiscoverableProviderOwnerPluginIds(params: {
315315
env?: PluginLoadOptions["env"];
316316
includeUntrustedWorkspacePlugins?: boolean;
317317
}): string[] {
318-
const shouldFilterUntrustedWorkspacePlugins = params.includeUntrustedWorkspacePlugins === false;
318+
const shouldFilterUntrustedWorkspacePlugins = params.includeUntrustedWorkspacePlugins !== true;
319319
const shouldFilterBundledByAllowlist = params.config?.plugins?.bundledDiscovery !== "compat";
320320
return resolveProviderOwnerPluginIds({
321321
...params,

0 commit comments

Comments
 (0)