Skip to content

Commit 00bd2cf

Browse files
committed
fix: allow installed plugins through allowlist
(cherry picked from commit d3dc890)
1 parent 71b7873 commit 00bd2cf

4 files changed

Lines changed: 87 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ Docs: https://docs.openclaw.ai
4444
- Thinking defaults/status: raise the implicit default thinking level for reasoning-capable models from legacy `off`/`low` fallback behavior to a safe provider-supported `medium` equivalent when no explicit config default is set, preserve configured-model reasoning metadata when runtime catalog loading is empty, and make `/status` report the same resolved default as runtime.
4545
- Gateway/model pricing: fetch OpenRouter and LiteLLM pricing asynchronously at startup and extend catalog fetch timeouts to 30 seconds, reducing noisy timeout warnings during slow upstream responses.
4646
- Agents/sessions: keep daily reset and idle-maintenance bookkeeping from bumping session activity or pruning freshly active routes, so active conversations no longer look newer or disappear for maintenance-only updates.
47+
- Plugins/install: add newly installed plugin ids to an existing `plugins.allow` list before enabling them, so allowlisted configs load installed plugins after restart.
4748
- Status: show `Fast` in `/status` when fast mode is enabled, including config/default-derived fast mode, and omit it when disabled.
4849
- OpenAI/image generation: detect Azure OpenAI-style image endpoints, use Azure `api-key` auth plus deployment-scoped image URLs, honor `AZURE_OPENAI_API_VERSION`, and document the Azure setup path so image generation and edits work against Azure-hosted OpenAI resources. (#70570) Thanks @zhanggpcsu.
4950
- Telegram/forum topics: cache recovered forum metadata with bounded expiry so supergroup updates no longer need repeated `getChat` lookups before topic routing.

docs/tools/plugin.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,10 @@ plugin). Other bundled plugins still need `openclaw plugins enable <id>`.
255255
plugins. It is not supported with `--link`, which reuses the source path instead
256256
of copying over a managed install target.
257257

258+
When `plugins.allow` is already set, `openclaw plugins install` adds the
259+
installed plugin id to that allowlist before enabling it, so installs are
260+
immediately loadable after restart.
261+
258262
`openclaw plugins update <id-or-npm-spec>` applies to tracked installs. Passing
259263
an npm package spec with a dist-tag or exact version resolves the package name
260264
back to the tracked plugin record and records the new spec for future updates.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { beforeEach, describe, expect, it } from "vitest";
2+
import type { OpenClawConfig } from "../config/config.js";
3+
import {
4+
enablePluginInConfig,
5+
recordPluginInstall,
6+
resetPluginsCliTestState,
7+
writeConfigFile,
8+
} from "./plugins-cli-test-helpers.js";
9+
10+
describe("persistPluginInstall", () => {
11+
beforeEach(() => {
12+
resetPluginsCliTestState();
13+
});
14+
15+
it("adds installed plugins to restrictive allowlists before enabling", async () => {
16+
const { persistPluginInstall } = await import("./plugins-install-persist.js");
17+
const baseConfig = {
18+
plugins: {
19+
allow: ["memory-core"],
20+
},
21+
} as OpenClawConfig;
22+
const enabledConfig = {
23+
plugins: {
24+
allow: ["alpha", "memory-core"],
25+
entries: {
26+
alpha: { enabled: true },
27+
},
28+
},
29+
} as OpenClawConfig;
30+
const persistedConfig = {
31+
plugins: {
32+
...enabledConfig.plugins,
33+
installs: {
34+
alpha: {
35+
source: "npm",
36+
37+
installPath: "/tmp/alpha",
38+
},
39+
},
40+
},
41+
} as OpenClawConfig;
42+
43+
enablePluginInConfig.mockImplementation((...args: unknown[]) => {
44+
const [cfg, pluginId] = args as [OpenClawConfig, string];
45+
expect(pluginId).toBe("alpha");
46+
expect(cfg.plugins?.allow).toEqual(["alpha", "memory-core"]);
47+
return { config: enabledConfig };
48+
});
49+
recordPluginInstall.mockReturnValue(persistedConfig);
50+
51+
const next = await persistPluginInstall({
52+
config: baseConfig,
53+
pluginId: "alpha",
54+
install: {
55+
source: "npm",
56+
57+
installPath: "/tmp/alpha",
58+
},
59+
});
60+
61+
expect(next).toBe(persistedConfig);
62+
expect(writeConfigFile).toHaveBeenCalledWith(persistedConfig);
63+
});
64+
});

src/cli/plugins-install-persist.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,20 @@ import {
1212
logSlotWarnings,
1313
} from "./plugins-command-helpers.js";
1414

15+
function addInstalledPluginToAllowlist(cfg: OpenClawConfig, pluginId: string): OpenClawConfig {
16+
const allow = cfg.plugins?.allow;
17+
if (!Array.isArray(allow) || allow.length === 0 || allow.includes(pluginId)) {
18+
return cfg;
19+
}
20+
return {
21+
...cfg,
22+
plugins: {
23+
...cfg.plugins,
24+
allow: [...allow, pluginId].toSorted(),
25+
},
26+
};
27+
}
28+
1529
export async function persistPluginInstall(params: {
1630
config: OpenClawConfig;
1731
baseHash?: string;
@@ -20,7 +34,10 @@ export async function persistPluginInstall(params: {
2034
successMessage?: string;
2135
warningMessage?: string;
2236
}): Promise<OpenClawConfig> {
23-
let next = enablePluginInConfig(params.config, params.pluginId).config;
37+
let next = enablePluginInConfig(
38+
addInstalledPluginToAllowlist(params.config, params.pluginId),
39+
params.pluginId,
40+
).config;
2441
next = recordPluginInstall(next, {
2542
pluginId: params.pluginId,
2643
...params.install,

0 commit comments

Comments
 (0)