From 4f2f5e04610c4dea689652d1d0cd8794156e8c3e Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Mon, 4 May 2026 05:17:11 -0700 Subject: [PATCH] test(feishu): cover native Windows webhook and workspace paths --- extensions/feishu/src/docx.test.ts | 14 ++-- .../src/monitor.webhook-security.test.ts | 68 +++++++++++++++++-- 2 files changed, 69 insertions(+), 13 deletions(-) diff --git a/extensions/feishu/src/docx.test.ts b/extensions/feishu/src/docx.test.ts index 5eb8013c236..afe0fce13f1 100644 --- a/extensions/feishu/src/docx.test.ts +++ b/extensions/feishu/src/docx.test.ts @@ -61,6 +61,8 @@ type ToolResultWithDetails = { details: Record; }; +const WORKSPACE_ROOT = path.resolve("/workspace"); + describe("feishu_doc image fetch hardening", () => { beforeEach(() => { vi.clearAllMocks(); @@ -505,7 +507,7 @@ describe("feishu_doc image fetch hardening", () => { }); const feishuDocTool = resolveFeishuDocTool({ - workspaceDir: "/workspace", + workspaceDir: WORKSPACE_ROOT, fsPolicy: { workspaceOnly: true }, }); @@ -518,7 +520,7 @@ describe("feishu_doc image fetch hardening", () => { expect(loadWebMediaMock).toHaveBeenCalledWith( expect.stringContaining("test-local.txt"), - expect.objectContaining({ optimizeImages: false, localRoots: ["/workspace"] }), + expect.objectContaining({ optimizeImages: false, localRoots: [WORKSPACE_ROOT] }), ); }); @@ -559,7 +561,7 @@ describe("feishu_doc image fetch hardening", () => { }); const feishuDocTool = resolveFeishuDocTool({ - workspaceDir: "/workspace", + workspaceDir: WORKSPACE_ROOT, fsPolicy: { workspaceOnly: true }, }); @@ -572,7 +574,7 @@ describe("feishu_doc image fetch hardening", () => { expect(loadWebMediaMock).toHaveBeenCalledWith( expect.stringContaining("test-local.png"), - expect.objectContaining({ optimizeImages: false, localRoots: ["/workspace"] }), + expect.objectContaining({ optimizeImages: false, localRoots: [WORKSPACE_ROOT] }), ); }); @@ -588,7 +590,7 @@ describe("feishu_doc image fetch hardening", () => { }); const feishuDocTool = resolveFeishuDocTool({ - workspaceDir: "/workspace", + workspaceDir: WORKSPACE_ROOT, fsPolicy: { workspaceOnly: true }, }); @@ -602,7 +604,7 @@ describe("feishu_doc image fetch hardening", () => { expect(loadWebMediaMock).toHaveBeenCalledWith( expect.stringContaining("absolute-image.png"), - expect.objectContaining({ optimizeImages: false, localRoots: ["/workspace"] }), + expect.objectContaining({ optimizeImages: false, localRoots: [WORKSPACE_ROOT] }), ); } finally { rmSync(fixtureDir, { recursive: true, force: true }); diff --git a/extensions/feishu/src/monitor.webhook-security.test.ts b/extensions/feishu/src/monitor.webhook-security.test.ts index 344897f1a14..432fd150b9b 100644 --- a/extensions/feishu/src/monitor.webhook-security.test.ts +++ b/extensions/feishu/src/monitor.webhook-security.test.ts @@ -88,6 +88,64 @@ async function waitForSlowBodyTimeoutResponse( }); } +async function waitForOversizedBodyResponse(url: string): Promise { + return await new Promise((resolve, reject) => { + const target = new URL(url); + const body = JSON.stringify({ payload: "x".repeat(70 * 1024) }); + let response = ""; + let settled = false; + const socket = createConnection( + { + host: target.hostname, + port: Number(target.port), + }, + () => { + socket.write(`POST ${target.pathname} HTTP/1.1\r\n`); + socket.write(`Host: ${target.hostname}\r\n`); + socket.write("Content-Type: application/json\r\n"); + socket.write(`Content-Length: ${Buffer.byteLength(body)}\r\n`); + socket.write("\r\n"); + socket.write(body); + }, + ); + + const finish = (result: string) => { + if (settled) { + return; + } + settled = true; + clearTimeout(failTimer); + socket.destroy(); + resolve(result); + }; + + socket.setEncoding("utf8"); + socket.on("data", (chunk) => { + response += chunk; + if (response.includes("Payload too large")) { + finish(response); + } + }); + socket.on("close", () => { + if (response.includes("Payload too large")) { + finish(response); + } + }); + socket.on("error", (error) => { + if (response.includes("Payload too large")) { + finish(response); + return; + } + reject(error); + }); + + const failTimer = setTimeout(() => { + socket.destroy(); + reject(new Error("payload-too-large response did not arrive within 1000ms")); + }, 1_000); + }); +} + afterEach(() => { clearFeishuWebhookRateLimitStateForTest(); stopFeishuMonitor(); @@ -182,14 +240,10 @@ describe("Feishu webhook security hardening", () => { }, monitorFeishuProvider, async (url) => { - const response = await fetch(url, { - method: "POST", - headers: { "content-type": "application/json" }, - body: JSON.stringify({ payload: "x".repeat(70 * 1024) }), - }); + const response = await waitForOversizedBodyResponse(url); - expect(response.status).toBe(413); - expect(await response.text()).toBe("Payload too large"); + expect(response).toContain("413 Payload Too Large"); + expect(response).toContain("Payload too large"); }, ); });