Skip to content

Commit 926cf98

Browse files
committed
fix: address issue
1 parent d0f7c8f commit 926cf98

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
@@ -937,7 +937,7 @@ describe("resolvePluginProviders", () => {
937937
});
938938
});
939939

940-
it("loads all discovered provider plugins in setup mode for explicit compat configs", () => {
940+
it("excludes untrusted workspace provider plugins from setup discovery by default", () => {
941941
resolvePluginProviders({
942942
config: {
943943
plugins: {
@@ -952,20 +952,36 @@ describe("resolvePluginProviders", () => {
952952
});
953953

954954
expectLastSetupRegistryLoad({
955-
onlyPluginIds: ["google", "kilocode", "moonshot", "workspace-provider"],
955+
onlyPluginIds: ["google", "kilocode", "moonshot"],
956956
});
957957
expectPluginConfigState(getLastSetupLoadedPluginConfig(), {
958-
allow: ["openrouter", "google", "kilocode", "moonshot", "workspace-provider"],
958+
allow: ["openrouter", "google", "kilocode", "moonshot"],
959959
entries: {
960960
google: { enabled: false },
961961
kilocode: { enabled: true },
962962
moonshot: { enabled: true },
963-
"workspace-provider": { enabled: true },
964963
},
965964
});
966965
});
967966

968-
it("excludes untrusted workspace provider plugins from setup discovery when requested", () => {
967+
it("loads explicitly included untrusted workspace provider plugins in setup discovery", () => {
968+
resolvePluginProviders({
969+
config: {
970+
plugins: {
971+
allow: ["openrouter"],
972+
bundledDiscovery: "compat",
973+
},
974+
},
975+
mode: "setup",
976+
includeUntrustedWorkspacePlugins: true,
977+
});
978+
979+
expectLastSetupRegistryLoad({
980+
onlyPluginIds: ["google", "kilocode", "moonshot", "workspace-provider"],
981+
});
982+
});
983+
984+
it("excludes untrusted workspace provider plugins from setup discovery when explicitly requested", () => {
969985
resolvePluginProviders({
970986
config: {
971987
plugins: {

src/plugins/providers.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ export function resolveDiscoveredProviderPluginIds(params: {
263263
}): string[] {
264264
const { registry, onlyPluginIdSet } = loadScopedProviderRegistry(params);
265265
const providerSurfacePluginIds = resolveProviderSurfacePluginIdSet({ ...params, registry });
266-
const shouldFilterUntrustedWorkspacePlugins = params.includeUntrustedWorkspacePlugins === false;
266+
const shouldFilterUntrustedWorkspacePlugins = params.includeUntrustedWorkspacePlugins !== true;
267267
const shouldFilterBundledByAllowlist = params.config?.plugins?.bundledDiscovery !== "compat";
268268
const normalizedConfig = normalizePluginsConfigWithRegistry(params.config?.plugins, registry, {
269269
manifestRegistry: params.manifestRegistry,
@@ -328,7 +328,7 @@ export function resolveDiscoverableProviderOwnerPluginIds(params: {
328328
manifestRegistry?: PluginManifestRegistry;
329329
includeUntrustedWorkspacePlugins?: boolean;
330330
}): string[] {
331-
const shouldFilterUntrustedWorkspacePlugins = params.includeUntrustedWorkspacePlugins === false;
331+
const shouldFilterUntrustedWorkspacePlugins = params.includeUntrustedWorkspacePlugins !== true;
332332
const shouldFilterBundledByAllowlist = params.config?.plugins?.bundledDiscovery !== "compat";
333333
return resolveProviderOwnerPluginIds({
334334
...params,

0 commit comments

Comments
 (0)