fix(telegram): support negative IDs in groupAllowFrom (#36753) (#37134)

* fix(telegram): support negative IDs in groupAllowFrom for group/channel whitelist (#36753)

When configuring Telegram group restrictions with groupAllowFrom,
negative group/channel IDs (e.g., -1001234567890) are rejected with
'authorization requires numeric Telegram sender IDs only' error,
even though the field name suggests it should accept group IDs.

Root cause:
- normalizeAllowFrom() uses regex /^\d+$/ to validate IDs
- Telegram group/channel IDs are negative integers
- Regex only matches positive integers, rejecting all group IDs

Impact:
- Users cannot whitelist specific groups using groupAllowFrom
- Workaround requires groupPolicy: "open" (security risk)
- Field name is misleading (suggests group IDs, but only accepts user IDs)

Fix:
- Change regex from /^\d+$/ to /^-?\d+$/ (support optional minus sign)
- Apply to both invalidEntries filter and ids filter
- Add comment explaining negative ID support for groups/channels

Testing:
- Positive user IDs (745123456) →  still work
- Negative group IDs (-1001234567890) →  now accepted
- Invalid entries (@username) → ⚠️  still warned

Fixes #36753

* test(telegram): add signed ID runtime regression

---------

Co-authored-by: Martin Qiu <qiuyuemartin@gmail.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
Martin-Max
2026-03-08 08:27:25 +08:00
committed by GitHub
parent 73e510cdf4
commit a7f6e0a921
2 changed files with 18 additions and 2 deletions

View File

@@ -0,0 +1,15 @@
import { describe, expect, it } from "vitest";
import { normalizeAllowFrom } from "./bot-access.js";
describe("normalizeAllowFrom", () => {
it("accepts signed numeric Telegram IDs and rejects usernames", () => {
const result = normalizeAllowFrom(["-1001234567890", " tg:-100999 ", "745123456", "@someone"]);
expect(result).toEqual({
entries: ["-1001234567890", "-100999", "745123456"],
hasWildcard: false,
hasEntries: true,
invalidEntries: ["@someone"],
});
});
});

View File

@@ -44,11 +44,12 @@ export const normalizeAllowFrom = (list?: Array<string | number>): NormalizedAll
const normalized = entries const normalized = entries
.filter((value) => value !== "*") .filter((value) => value !== "*")
.map((value) => value.replace(/^(telegram|tg):/i, "")); .map((value) => value.replace(/^(telegram|tg):/i, ""));
const invalidEntries = normalized.filter((value) => !/^\d+$/.test(value)); // Support negative IDs for Telegram group/channel IDs (e.g., -1001234567890)
const invalidEntries = normalized.filter((value) => !/^-?\d+$/.test(value));
if (invalidEntries.length > 0) { if (invalidEntries.length > 0) {
warnInvalidAllowFromEntries([...new Set(invalidEntries)]); warnInvalidAllowFromEntries([...new Set(invalidEntries)]);
} }
const ids = normalized.filter((value) => /^\d+$/.test(value)); const ids = normalized.filter((value) => /^-?\d+$/.test(value));
return { return {
entries: ids, entries: ids,
hasWildcard, hasWildcard,