From f89c2982f0503d0b2c1d0b5d27ce1bb7e640a377 Mon Sep 17 00:00:00 2001 From: saurav470 Date: Sun, 8 Mar 2026 13:38:43 +0530 Subject: [PATCH] fix(feishu): enhance media handling to respect explicit empty localRoots and update related tests --- extensions/feishu/src/media.test.ts | 28 ++++++++++++++++++++++++++++ extensions/feishu/src/media.ts | 3 ++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/extensions/feishu/src/media.test.ts b/extensions/feishu/src/media.test.ts index 906a4170772..44a4ddb4e99 100644 --- a/extensions/feishu/src/media.test.ts +++ b/extensions/feishu/src/media.test.ts @@ -345,6 +345,34 @@ describe("sendMediaFeishu msg_type routing", () => { ); }); + it("honors explicit empty localRoots (no fallback to context mediaLocalRoots)", async () => { + resolveFeishuAccountMock.mockReturnValueOnce({ + configured: true, + accountId: "main", + config: { localRoots: [] }, + }); + loadWebMediaMock.mockRejectedValueOnce( + new (class extends Error { + code = "path-not-allowed"; + name = "LocalMediaAccessError"; + })(), + ); + + await expect( + sendMediaFeishu({ + cfg: {} as any, + to: "user:ou_target", + mediaUrl: "/some/local/file.png", + mediaLocalRoots: ["/allowed/context/root"], + }), + ).rejects.toMatchObject({ code: "path-not-allowed" }); + + expect(loadWebMediaMock).toHaveBeenCalledWith( + "/some/local/file.png", + expect.objectContaining({ localRoots: [] }), + ); + }); + it("fails closed when media URL fetch is blocked", async () => { loadWebMediaMock.mockRejectedValueOnce( new Error("Blocked: resolves to private/internal IP address"), diff --git a/extensions/feishu/src/media.ts b/extensions/feishu/src/media.ts index db95a07a51e..c5bc09f006f 100644 --- a/extensions/feishu/src/media.ts +++ b/extensions/feishu/src/media.ts @@ -426,7 +426,8 @@ function resolveFeishuMediaLocalRoots(params: { if (channelRoots === "any") { return "any"; } - if (Array.isArray(channelRoots) && channelRoots.length > 0) { + // Honor explicit array (including empty): [] means disable local-path reads for Feishu. + if (Array.isArray(channelRoots)) { return channelRoots; } return params.mediaLocalRoots?.length ? params.mediaLocalRoots : undefined;