fix: preserve configured plugins in allowlist

This commit is contained in:
Peter Steinberger
2026-04-11 02:08:10 +01:00
parent 202f80792e
commit dc008f956c
2 changed files with 118 additions and 9 deletions

View File

@@ -256,8 +256,16 @@ function hasConfiguredPluginConfigEntry(cfg: OpenClawConfig): boolean {
);
}
function hasPluginEntries(cfg: OpenClawConfig): boolean {
const entries = cfg.plugins?.entries;
return !!entries && typeof entries === "object" && Object.keys(entries).length > 0;
}
function configMayNeedPluginManifestRegistry(cfg: OpenClawConfig): boolean {
const pluginEntries = cfg.plugins?.entries;
if (Array.isArray(cfg.plugins?.allow) && cfg.plugins.allow.length > 0 && hasPluginEntries(cfg)) {
return true;
}
if (
pluginEntries &&
Object.values(pluginEntries).some((entry) => isRecord(entry) && isRecord(entry.config))
@@ -292,6 +300,9 @@ export function configMayNeedPluginAutoEnable(
cfg: OpenClawConfig,
env: NodeJS.ProcessEnv,
): boolean {
if (Array.isArray(cfg.plugins?.allow) && cfg.plugins.allow.length > 0 && hasPluginEntries(cfg)) {
return true;
}
if (hasConfiguredPluginConfigEntry(cfg)) {
return true;
}
@@ -500,6 +511,59 @@ function registerPluginEntry(cfg: OpenClawConfig, pluginId: string): OpenClawCon
};
}
function hasMaterialPluginEntryConfig(entry: unknown): boolean {
if (!isRecord(entry)) {
return false;
}
return (
entry.enabled === true ||
isRecord(entry.config) ||
isRecord(entry.hooks) ||
isRecord(entry.subagent) ||
entry.apiKey !== undefined ||
entry.env !== undefined
);
}
function isKnownPluginId(pluginId: string, manifestRegistry: PluginManifestRegistry): boolean {
if (normalizeChatChannelId(pluginId)) {
return true;
}
return manifestRegistry.plugins.some((plugin) => plugin.id === pluginId);
}
function materializeConfiguredPluginEntryAllowlist(params: {
config: OpenClawConfig;
changes: string[];
manifestRegistry: PluginManifestRegistry;
}): OpenClawConfig {
let next = params.config;
const allow = next.plugins?.allow;
const entries = next.plugins?.entries;
if (!Array.isArray(allow) || allow.length === 0 || !entries || typeof entries !== "object") {
return next;
}
for (const pluginId of Object.keys(entries).toSorted((left, right) =>
left.localeCompare(right),
)) {
const entry = entries[pluginId];
if (
!hasMaterialPluginEntryConfig(entry) ||
isPluginDenied(next, pluginId) ||
isPluginExplicitlyDisabled(next, pluginId) ||
allow.includes(pluginId) ||
!isKnownPluginId(pluginId, params.manifestRegistry)
) {
continue;
}
next = ensurePluginAllowlisted(next, pluginId);
params.changes.push(`${pluginId} plugin config present, added to plugin allowlist.`);
}
return next;
}
function formatAutoEnableChange(entry: PluginAutoEnableCandidate): string {
let reason = resolvePluginAutoEnableCandidateReason(entry).trim();
const channelId = normalizeChatChannelId(entry.pluginId);
@@ -557,8 +621,7 @@ export function materializePluginAutoEnableCandidatesInternal(params: {
}
const allow = next.plugins?.allow;
const allowMissing =
builtInChannelId == null && Array.isArray(allow) && !allow.includes(entry.pluginId);
const allowMissing = Array.isArray(allow) && !allow.includes(entry.pluginId);
const alreadyEnabled =
builtInChannelId != null
? isBuiltInChannelAlreadyEnabled(next, builtInChannelId)
@@ -568,9 +631,7 @@ export function materializePluginAutoEnableCandidatesInternal(params: {
}
next = registerPluginEntry(next, entry.pluginId);
if (!builtInChannelId) {
next = ensurePluginAllowlisted(next, entry.pluginId);
}
next = ensurePluginAllowlisted(next, entry.pluginId);
const reason = resolvePluginAutoEnableCandidateReason(entry);
autoEnabledReasons.set(entry.pluginId, [
...(autoEnabledReasons.get(entry.pluginId) ?? []),
@@ -579,6 +640,12 @@ export function materializePluginAutoEnableCandidatesInternal(params: {
changes.push(formatAutoEnableChange(entry));
}
next = materializeConfiguredPluginEntryAllowlist({
config: next,
changes,
manifestRegistry: params.manifestRegistry,
});
const autoEnabledReasonRecord: Record<string, string[]> = Object.create(null);
for (const [pluginId, reasons] of autoEnabledReasons) {
if (!isBlockedObjectKey(pluginId)) {