fix(cron): validate Telegram delivery targets to reject invalid formats

Reject cron jobs with Telegram delivery targets using chatId/topicId
format (e.g. "-10012345/6789") which are not supported. Allow valid
formats: plain chat ID, colon delimiter (:), @username, and t.me URLs.

Added validateTelegramDeliveryTarget() function and tests.
This commit is contained in:
Evgeny Zislis 2026-02-20 19:11:24 +02:00 committed by Ayaan Zaidi
parent d58661f8bb
commit 2d70646e8d
2 changed files with 24 additions and 12 deletions

View File

@ -153,7 +153,7 @@ describe("applyJobPatch", () => {
expect(job.delivery).toEqual({ mode: "webhook", to: "https://example.invalid/trim" });
});
it("rejects Telegram delivery with invalid target (slash delimiter)", () => {
it("rejects Telegram delivery with invalid target (chatId/topicId format)", () => {
const job = createIsolatedAgentTurnJob("job-telegram-invalid", {
mode: "announce",
channel: "telegram",
@ -161,20 +161,28 @@ describe("applyJobPatch", () => {
});
expect(() => applyJobPatch(job, { enabled: true })).toThrow(
'Invalid Telegram delivery target "-10012345/6789". Use colon (:) as delimiter, not slash or other characters. Valid formats: -1001234567890, -1001234567890:123, -1001234567890:topic:123',
'Invalid Telegram delivery target "-10012345/6789". Use colon (:) as delimiter for topics, not slash. Valid formats: -1001234567890, -1001234567890:123, -1001234567890:topic:123, @username, https://t.me/username',
);
});
it("rejects Telegram delivery with other invalid characters", () => {
const job = createIsolatedAgentTurnJob("job-telegram-invalid-space", {
it("accepts Telegram delivery with t.me URL", () => {
const job = createIsolatedAgentTurnJob("job-telegram-tme", {
mode: "announce",
channel: "telegram",
to: "-10012345 6789",
to: "https://t.me/mychannel",
});
expect(() => applyJobPatch(job, { enabled: true })).toThrow(
'Invalid Telegram delivery target "-10012345 6789". Use colon (:) as delimiter, not slash or other characters. Valid formats: -1001234567890, -1001234567890:123, -1001234567890:topic:123',
);
expect(() => applyJobPatch(job, { enabled: true })).not.toThrow();
});
it("accepts Telegram delivery with t.me URL (no https)", () => {
const job = createIsolatedAgentTurnJob("job-telegram-tme-no-https", {
mode: "announce",
channel: "telegram",
to: "t.me/mychannel",
});
expect(() => applyJobPatch(job, { enabled: true })).not.toThrow();
});
it("accepts Telegram delivery with valid target (plain chat id)", () => {

View File

@ -83,15 +83,19 @@ export function assertSupportedJobSpec(job: Pick<CronJob, "sessionTarget" | "pay
}
}
const INVALID_TELEGRAM_TARGET_CHARS = ["/", "\\", " ", ",", ";"];
const TELEGRAM_TME_URL_REGEX = /^https?:\/\/t\.me\/|t\.me\//i;
const TELEGRAM_SLASH_TOPIC_REGEX = /^-?\d+\/\d+$/;
function validateTelegramDeliveryTarget(to: string | undefined): string | undefined {
if (!to) {
return undefined;
}
const hasInvalidChar = INVALID_TELEGRAM_TARGET_CHARS.some((char) => to.includes(char));
if (hasInvalidChar) {
return `Invalid Telegram delivery target "${to}". Use colon (:) as delimiter, not slash or other characters. Valid formats: -1001234567890, -1001234567890:123, -1001234567890:topic:123`;
const trimmed = to.trim();
if (TELEGRAM_TME_URL_REGEX.test(trimmed)) {
return undefined;
}
if (TELEGRAM_SLASH_TOPIC_REGEX.test(trimmed)) {
return `Invalid Telegram delivery target "${to}". Use colon (:) as delimiter for topics, not slash. Valid formats: -1001234567890, -1001234567890:123, -1001234567890:topic:123, @username, https://t.me/username`;
}
return undefined;
}