fix(telegram): warn when setup leaves dmPolicy as pairing without allowFrom (#50710)
* fix(telegram): warn when setup leaves dmPolicy as pairing without allowFrom * fix(telegram): scope setup warning to account config * fix(telegram): quote setup allowFrom example * fix: warn on insecure Telegram setup defaults (#50710) (thanks @ernestodeoliveira) --------- Co-authored-by: Claude Code <claude-code@openclaw.ai> Co-authored-by: Ayaan Zaidi <hi@obviy.us>
This commit is contained in:
parent
991eb2ef03
commit
80110c550f
@ -78,6 +78,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Agents/compaction: extend the enclosing run deadline once while compaction is actively in flight, and abort the underlying SDK compaction on timeout/cancel so large-session compactions stop freezing mid-run. (#46889) Thanks @asyncjason.
|
||||
- Agents/openai-compatible tool calls: deduplicate repeated tool call ids across live assistant messages and replayed history so OpenAI-compatible backends no longer reject duplicate `tool_call_id` values with HTTP 400. (#40996) Thanks @xaeon2026.
|
||||
- Models/openai-completions: default non-native OpenAI-compatible providers to omit tool-definition `strict` fields unless users explicitly opt back in, so tool calling keeps working on providers that reject that option. (#45497) Thanks @sahancava.
|
||||
- Telegram/setup: warn when setup leaves DMs on pairing without an allowlist, and show valid account-scoped remediation commands. (#50710) Thanks @ernestodeoliveira.
|
||||
- Models/OpenRouter runtime capabilities: fetch uncatalogued OpenRouter model metadata on first use so newly added vision models keep image input instead of silently degrading to text-only, with top-level capability field fallbacks for `/api/v1/models`. (#45824) Thanks @DJjjjhao.
|
||||
- Channels/plugins: keep shared interactive payloads merge-ready by fixing Slack custom callback routing and repeat-click dedupe, allowing interactive-only sends, and preserving ordered Discord shared text blocks. (#47715) Thanks @vincentkoc.
|
||||
- Slack/interactive replies: preserve `channelData.slack.blocks` through live DM delivery and preview-finalized edits so Block Kit button and select directives render instead of falling back to raw text. (#45890) Thanks @vincentkoc.
|
||||
|
||||
91
extensions/telegram/src/setup-surface.test.ts
Normal file
91
extensions/telegram/src/setup-surface.test.ts
Normal file
@ -0,0 +1,91 @@
|
||||
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/setup";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../../../src/config/config.js";
|
||||
import { telegramSetupWizard } from "./setup-surface.js";
|
||||
|
||||
async function runFinalize(cfg: OpenClawConfig, accountId: string) {
|
||||
const prompter = {
|
||||
note: vi.fn(async () => undefined),
|
||||
};
|
||||
|
||||
await telegramSetupWizard.finalize?.({
|
||||
cfg,
|
||||
accountId,
|
||||
credentialValues: {},
|
||||
runtime: {} as never,
|
||||
prompter: prompter as never,
|
||||
forceAllowFrom: false,
|
||||
});
|
||||
|
||||
return prompter.note;
|
||||
}
|
||||
|
||||
describe("telegramSetupWizard.finalize", () => {
|
||||
it("shows global config commands for the default account", async () => {
|
||||
const note = await runFinalize(
|
||||
{
|
||||
channels: {
|
||||
telegram: {
|
||||
botToken: "tok",
|
||||
},
|
||||
},
|
||||
},
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
);
|
||||
|
||||
expect(note).toHaveBeenCalledWith(
|
||||
expect.stringContaining('openclaw config set channels.telegram.dmPolicy "allowlist"'),
|
||||
"Telegram DM access warning",
|
||||
);
|
||||
expect(note).toHaveBeenCalledWith(
|
||||
expect.stringContaining(`openclaw config set channels.telegram.allowFrom '["YOUR_USER_ID"]'`),
|
||||
"Telegram DM access warning",
|
||||
);
|
||||
});
|
||||
|
||||
it("shows account-scoped config commands for named accounts", async () => {
|
||||
const note = await runFinalize(
|
||||
{
|
||||
channels: {
|
||||
telegram: {
|
||||
accounts: {
|
||||
alerts: {
|
||||
botToken: "tok",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"alerts",
|
||||
);
|
||||
|
||||
expect(note).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
'openclaw config set channels.telegram.accounts.alerts.dmPolicy "allowlist"',
|
||||
),
|
||||
"Telegram DM access warning",
|
||||
);
|
||||
expect(note).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
`openclaw config set channels.telegram.accounts.alerts.allowFrom '["YOUR_USER_ID"]'`,
|
||||
),
|
||||
"Telegram DM access warning",
|
||||
);
|
||||
});
|
||||
|
||||
it("skips the warning when an allowFrom entry already exists", async () => {
|
||||
const note = await runFinalize(
|
||||
{
|
||||
channels: {
|
||||
telegram: {
|
||||
botToken: "tok",
|
||||
allowFrom: ["123"],
|
||||
},
|
||||
},
|
||||
},
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
);
|
||||
|
||||
expect(note).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@ -9,8 +9,13 @@ import {
|
||||
splitSetupEntries,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import type { ChannelSetupDmPolicy, ChannelSetupWizard } from "openclaw/plugin-sdk/setup";
|
||||
import { formatCliCommand, formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
|
||||
import { inspectTelegramAccount } from "./account-inspect.js";
|
||||
import { listTelegramAccountIds, resolveTelegramAccount } from "./accounts.js";
|
||||
import {
|
||||
listTelegramAccountIds,
|
||||
mergeTelegramAccountConfig,
|
||||
resolveTelegramAccount,
|
||||
} from "./accounts.js";
|
||||
import {
|
||||
parseTelegramAllowFromId,
|
||||
promptTelegramAllowFromForAccount,
|
||||
@ -22,6 +27,29 @@ import {
|
||||
|
||||
const channel = "telegram" as const;
|
||||
|
||||
function shouldShowTelegramDmAccessWarning(cfg: OpenClawConfig, accountId: string): boolean {
|
||||
const merged = mergeTelegramAccountConfig(cfg, accountId);
|
||||
const policy = merged.dmPolicy ?? "pairing";
|
||||
const hasAllowFrom =
|
||||
Array.isArray(merged.allowFrom) && merged.allowFrom.some((e) => String(e).trim());
|
||||
return policy === "pairing" && !hasAllowFrom;
|
||||
}
|
||||
|
||||
function buildTelegramDmAccessWarningLines(accountId: string): string[] {
|
||||
const configBase =
|
||||
accountId === DEFAULT_ACCOUNT_ID
|
||||
? "channels.telegram"
|
||||
: `channels.telegram.accounts.${accountId}`;
|
||||
return [
|
||||
"Your bot is using DM policy: pairing.",
|
||||
"Any Telegram user who discovers the bot can send pairing requests.",
|
||||
"For private use, configure an allowlist with your Telegram user id:",
|
||||
" " + formatCliCommand(`openclaw config set ${configBase}.dmPolicy "allowlist"`),
|
||||
" " + formatCliCommand(`openclaw config set ${configBase}.allowFrom '["YOUR_USER_ID"]'`),
|
||||
`Docs: ${formatDocsLink("/channels/pairing", "channels/pairing")}`,
|
||||
];
|
||||
}
|
||||
|
||||
const dmPolicy: ChannelSetupDmPolicy = {
|
||||
label: "Telegram",
|
||||
channel,
|
||||
@ -104,6 +132,15 @@ export const telegramSetupWizard: ChannelSetupWizard = {
|
||||
patch: { dmPolicy: "allowlist", allowFrom },
|
||||
}),
|
||||
}),
|
||||
finalize: async ({ cfg, accountId, prompter }) => {
|
||||
if (!shouldShowTelegramDmAccessWarning(cfg, accountId)) {
|
||||
return;
|
||||
}
|
||||
await prompter.note(
|
||||
buildTelegramDmAccessWarningLines(accountId).join("\n"),
|
||||
"Telegram DM access warning",
|
||||
);
|
||||
},
|
||||
dmPolicy,
|
||||
disable: (cfg) => setSetupChannelEnabled(cfg, channel, false),
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user