fix(security): enforce bounded webhook body handling

This commit is contained in:
Peter Steinberger
2026-02-13 19:14:36 +01:00
parent 2f9c523bbe
commit 3cbcba10cf
20 changed files with 834 additions and 281 deletions

View File

@@ -1,6 +1,11 @@
import type { ClawdbotConfig, RuntimeEnv, HistoryEntry } from "openclaw/plugin-sdk";
import * as Lark from "@larksuiteoapi/node-sdk";
import * as http from "http";
import {
type ClawdbotConfig,
type RuntimeEnv,
type HistoryEntry,
installRequestBodyLimitGuard,
} from "openclaw/plugin-sdk";
import type { ResolvedFeishuAccount } from "./types.js";
import { resolveFeishuAccount, listEnabledFeishuAccounts } from "./accounts.js";
import { handleFeishuMessage, type FeishuMessageEvent, type FeishuBotAddedEvent } from "./bot.js";
@@ -18,6 +23,8 @@ export type MonitorFeishuOpts = {
const wsClients = new Map<string, Lark.WSClient>();
const httpServers = new Map<string, http.Server>();
const botOpenIds = new Map<string, string>();
const FEISHU_WEBHOOK_MAX_BODY_BYTES = 1024 * 1024;
const FEISHU_WEBHOOK_BODY_TIMEOUT_MS = 30_000;
async function fetchBotOpenId(account: ResolvedFeishuAccount): Promise<string | undefined> {
try {
@@ -197,7 +204,26 @@ async function monitorWebhook({
log(`feishu[${accountId}]: starting Webhook server on port ${port}, path ${path}...`);
const server = http.createServer();
server.on("request", Lark.adaptDefault(path, eventDispatcher, { autoChallenge: true }));
const webhookHandler = Lark.adaptDefault(path, eventDispatcher, { autoChallenge: true });
server.on("request", (req, res) => {
const guard = installRequestBodyLimitGuard(req, res, {
maxBytes: FEISHU_WEBHOOK_MAX_BODY_BYTES,
timeoutMs: FEISHU_WEBHOOK_BODY_TIMEOUT_MS,
responseFormat: "text",
});
if (guard.isTripped()) {
return;
}
void Promise.resolve(webhookHandler(req, res))
.catch((err) => {
if (!guard.isTripped()) {
error(`feishu[${accountId}]: webhook handler error: ${String(err)}`);
}
})
.finally(() => {
guard.dispose();
});
});
httpServers.set(accountId, server);
return new Promise((resolve, reject) => {