fix(plugins): keep auto-enabled channels behind allowlists

This commit is contained in:
Doruk Ardahan
2026-04-03 14:54:41 +03:00
committed by Peter Steinberger
parent f7d24c1ed5
commit cd08facd7a
4 changed files with 76 additions and 2 deletions

View File

@@ -351,6 +351,36 @@ describe("resolveEffectivePluginActivationState", () => {
});
});
it("keeps denylist authoritative over explicit bundled channel activation", () => {
const rawConfig = {
channels: {
telegram: {
enabled: true,
},
},
plugins: {
deny: ["telegram"],
},
};
expect(
resolveEffectivePluginActivationState({
id: "telegram",
origin: "bundled",
config: normalizePluginsConfig(rawConfig.plugins),
rootConfig: rawConfig,
sourceConfig: normalizePluginsConfig(rawConfig.plugins),
sourceRootConfig: rawConfig,
}),
).toEqual({
enabled: false,
activated: false,
explicitlyEnabled: true,
source: "disabled",
reason: "blocked by denylist",
});
});
it("does not let auto-enable reasons bypass the allowlist", () => {
const rawConfig = {
plugins: {

View File

@@ -287,8 +287,7 @@ export function resolvePluginActivationState(params: {
});
const explicitlyConfiguredBundledChannel =
params.origin === "bundled" &&
explicitSelection.reason === "channel enabled in config" &&
explicitSelection.explicitlyEnabled;
isBundledChannelEnabledByChannelConfig(params.sourceRootConfig ?? params.rootConfig, params.id);
if (!params.config.enabled) {
return {
@@ -451,6 +450,8 @@ export function resolveEffectiveEnableState(params: {
config: NormalizedPluginsConfig;
rootConfig?: OpenClawConfig;
enabledByDefault?: boolean;
sourceConfig?: NormalizedPluginsConfig;
sourceRootConfig?: OpenClawConfig;
}): { enabled: boolean; reason?: string } {
const state = resolveEffectivePluginActivationState(params);
return state.enabled ? { enabled: true } : { enabled: false, reason: state.reason };

View File

@@ -1098,6 +1098,36 @@ describe("loadOpenClawPlugins", () => {
});
});
it("keeps auto-enabled bundled channels behind restrictive allowlists", () => {
setupBundledTelegramPlugin();
const rawConfig = {
channels: {
telegram: {
botToken: "x",
},
},
plugins: {
allow: ["browser"],
},
} satisfies PluginLoadConfig;
const autoEnabled = applyPluginAutoEnable({
config: rawConfig,
env: {},
});
const registry = loadOpenClawPlugins({
cache: false,
workspaceDir: cachedBundledTelegramDir,
config: autoEnabled.config,
activationSourceConfig: rawConfig,
autoEnabledReasons: autoEnabled.autoEnabledReasons,
});
const telegram = registry.plugins.find((entry) => entry.id === "telegram");
expect(telegram?.status).toBe("disabled");
expect(telegram?.error).toBe("not in allowlist");
});
it("preserves all auto-enable reasons in activation metadata", () => {
setupBundledTelegramPlugin();
const rawConfig = {

View File

@@ -3,6 +3,7 @@ import fs from "node:fs";
import path from "node:path";
import { createJiti } from "jiti";
import type { ChannelPlugin } from "../channels/plugins/types.js";
import { normalizeChatChannelId } from "../channels/registry.js";
import { isChannelConfigured } from "../config/channel-configured.js";
import type { OpenClawConfig } from "../config/config.js";
import type { PluginInstallRecord } from "../config/types.plugins.js";
@@ -1166,6 +1167,12 @@ export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegi
config: normalized,
rootConfig: cfg,
enabledByDefault: manifestRecord.enabledByDefault,
...(normalizeChatChannelId(pluginId)
? {
sourceConfig: activationSourceNormalized,
sourceRootConfig: activationSourceConfig,
}
: {}),
});
const entry = normalized.entries[pluginId];
const record = createPluginRecord({
@@ -1717,6 +1724,12 @@ export async function loadOpenClawPluginCliRegistry(
config: normalized,
rootConfig: cfg,
enabledByDefault: manifestRecord.enabledByDefault,
...(normalizeChatChannelId(pluginId)
? {
sourceConfig: activationSourceNormalized,
sourceRootConfig: activationSourceConfig,
}
: {}),
});
const entry = normalized.entries[pluginId];
const record = createPluginRecord({