diff --git a/src/cli/command-secret-targets.import.test.ts b/src/cli/command-secret-targets.import.test.ts index 7f71795571e..1f3d8f8bca5 100644 --- a/src/cli/command-secret-targets.import.test.ts +++ b/src/cli/command-secret-targets.import.test.ts @@ -48,6 +48,29 @@ describe("command secret targets module import", () => { includeInConfigure: true, includeInAudit: true, }, + { + id: "channels.telegram.gatewayToken", + targetType: "gateway.auth.token", + configFile: "openclaw.json", + pathPattern: "gateway.auth.token", + secretShape: "secret_input", + expectedResolvedValue: "string", + includeInPlan: true, + includeInConfigure: true, + includeInAudit: true, + }, + { + id: "channels.telegram.gatewayTokenRef", + targetType: "channels.telegram.gatewayTokenRef", + configFile: "openclaw.json", + pathPattern: "channels.telegram.gatewayToken", + refPathPattern: "gateway.auth.token", + secretShape: "sibling_ref", + expectedResolvedValue: "string", + includeInPlan: true, + includeInConfigure: true, + includeInAudit: true, + }, ], }, }, @@ -67,6 +90,8 @@ describe("command secret targets module import", () => { }); expect(targets.has("channels.telegram.botToken")).toBe(true); + expect(targets.has("channels.telegram.gatewayToken")).toBe(false); + expect(targets.has("channels.telegram.gatewayTokenRef")).toBe(false); expect(targets.has("agents.defaults.memorySearch.remote.apiKey")).toBe(true); expect(listReadOnlyChannelPluginsForConfig).toHaveBeenCalledWith( expect.any(Object), diff --git a/src/cli/command-secret-targets.ts b/src/cli/command-secret-targets.ts index e14223b3512..b54027e43a8 100644 --- a/src/cli/command-secret-targets.ts +++ b/src/cli/command-secret-targets.ts @@ -74,6 +74,26 @@ function getChannelSecretTargetIds(): string[] { return cachedChannelSecretTargetIds; } +function isScopedChannelSecretTargetEntry(params: { + pluginId: string; + entry: { + id: string; + configFile?: string; + pathPattern?: string; + refPathPattern?: string; + }; +}): boolean { + const allowedPrefix = `channels.${params.pluginId}.`; + return ( + params.entry.id.startsWith(allowedPrefix) && + params.entry.configFile === "openclaw.json" && + typeof params.entry.pathPattern === "string" && + params.entry.pathPattern.startsWith(allowedPrefix) && + (params.entry.refPathPattern === undefined || + params.entry.refPathPattern.startsWith(allowedPrefix)) + ); +} + function getConfiguredChannelSecretTargetIds( config: OpenClawConfig, env: NodeJS.ProcessEnv = process.env, @@ -84,7 +104,7 @@ function getConfiguredChannelSecretTargetIds( includePersistedAuthState: false, })) { for (const entry of plugin.secrets?.secretTargetRegistryEntries ?? []) { - if (entry.id.startsWith(`channels.${plugin.id}.`)) { + if (isScopedChannelSecretTargetEntry({ pluginId: plugin.id, entry })) { targetIds.add(entry.id); } }