fix(feishu): validate message create time

This commit is contained in:
Peter Steinberger
2026-05-29 09:12:06 -04:00
parent 5fbeffd56b
commit 001da78fab
2 changed files with 40 additions and 4 deletions

View File

@@ -1311,6 +1311,42 @@ describe("handleFeishuMessage command authorization", () => {
expect(call.Timestamp).toBeLessThanOrEqual(after);
});
it("falls back to Date.now() when create_time is malformed", async () => {
mockShouldComputeCommandAuthorized.mockReturnValue(false);
const cfg: ClawdbotConfig = {
channels: {
feishu: {
dmPolicy: "open",
},
},
} as ClawdbotConfig;
const event: FeishuMessageEvent = {
sender: {
sender_id: {
open_id: "ou-attacker",
},
},
message: {
message_id: "msg-malformed-create-time",
chat_id: "oc-dm",
chat_type: "p2p",
message_type: "text",
content: JSON.stringify({ text: "hello" }),
create_time: "1700000000000ms",
},
};
const before = Date.now();
await dispatchMessage({ cfg, event });
const after = Date.now();
const call = mockFinalizeInboundContext.mock.calls.at(0)?.[0] as { Timestamp: number };
expect(call.Timestamp).toBeGreaterThanOrEqual(before);
expect(call.Timestamp).toBeLessThanOrEqual(after);
});
it("replies pairing challenge to DM chat_id instead of user:sender id", async () => {
const cfg: ClawdbotConfig = {
channels: {

View File

@@ -10,6 +10,7 @@ import {
resolveConfiguredBindingRoute,
resolveRuntimeConversationBindingRoute,
} from "openclaw/plugin-sdk/conversation-runtime";
import { parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
import {
DEFAULT_GROUP_HISTORY_LIMIT,
createChannelHistoryWindow,
@@ -604,10 +605,9 @@ export async function handleFeishuMessage(params: {
// Parse message create_time early so every downstream consumer (pending
// history, inbound payload, etc.) uses the original authoring timestamp
// instead of the delivery/processing time. Feishu uses a millisecond
// epoch string; fall back to Date.now() only when the field is absent.
const messageCreateTimeMs = event.message.create_time
? Number.parseInt(event.message.create_time, 10)
: Date.now();
// epoch string; fall back to Date.now() when absent or malformed.
const messageCreateTimeMs =
parseStrictNonNegativeInteger(event.message.create_time) ?? Date.now();
let requireMention = false; // DMs never require mention; groups may override below
if (isGroup) {