telegram: reject fractional ids in strict integer paths

This commit is contained in:
OpenClaw Agent 2026-03-11 14:39:50 +01:00
parent 88316f7c82
commit cda6b856d7
4 changed files with 29 additions and 3 deletions

View File

@ -71,6 +71,7 @@ function readTelegramMessageIdParam(
required,
integer: true,
strict: true,
strictInteger: true,
});
if (required && typeof messageId !== "number") {
throw new Error("messageId is required.");

View File

@ -63,6 +63,13 @@ describe("readNumberParam", () => {
expect(readNumberParam(params, "messageId", { integer: true })).toBe(42);
});
it("rejects fractional values when strictInteger is true", () => {
const params = { messageId: "42.9" };
expect(() =>
readNumberParam(params, "messageId", { integer: true, strictInteger: true }),
).toThrow(/messageId must be an integer/);
});
it("accepts snake_case aliases for camelCase keys", () => {
const params = { message_id: "42" };
expect(readNumberParam(params, "messageId")).toBe(42);

View File

@ -116,9 +116,16 @@ export function readStringOrNumberParam(
export function readNumberParam(
params: Record<string, unknown>,
key: string,
options: { required?: boolean; label?: string; integer?: boolean; strict?: boolean } = {},
options: {
required?: boolean;
label?: string;
integer?: boolean;
strict?: boolean;
strictInteger?: boolean;
} = {},
): number | undefined {
const { required = false, label = key, integer = false, strict = false } = options;
const { required = false, label = key, integer = false, strict = false, strictInteger = false } =
options;
const raw = readParamRaw(params, key);
let value: number | undefined;
if (typeof raw === "number" && Number.isFinite(raw)) {
@ -138,7 +145,13 @@ export function readNumberParam(
}
return undefined;
}
return integer ? Math.trunc(value) : value;
if (integer) {
if (strictInteger && !Number.isInteger(value)) {
throw new ToolInputError(`${label} must be an integer`);
}
return Math.trunc(value);
}
return value;
}
export function readStringArrayParam(

View File

@ -136,6 +136,8 @@ export async function handleTelegramAction(
});
const messageId = readNumberParam(params, "messageId", {
integer: true,
strict: true,
strictInteger: true,
});
if (typeof messageId !== "number" || !Number.isFinite(messageId) || messageId <= 0) {
return jsonResult({
@ -328,6 +330,7 @@ export async function handleTelegramAction(
required: true,
integer: true,
strict: true,
strictInteger: true,
});
const token = resolveTelegramToken(cfg, { accountId }).token;
if (!token) {
@ -380,6 +383,8 @@ export async function handleTelegramAction(
const messageId = readNumberParam(params, "messageId", {
required: true,
integer: true,
strict: true,
strictInteger: true,
});
const content = readStringParam(params, "content", {
required: true,