mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-08 06:54:24 +00:00
fix(feishu): land #31209 prevent system preview leakage (@stakeswky)
Landed from contributor PR #31209 by @stakeswky. Co-authored-by: stakeswky <stakeswky@users.noreply.github.com>
This commit is contained in:
@@ -113,7 +113,8 @@ Docs: https://docs.openclaw.ai
|
||||
### Fixes
|
||||
|
||||
- Signal/Sync message null-handling: treat `syncMessage` presence (including `null`) as sync envelope traffic so replayed sentTranscript payloads cannot bypass loop guards after daemon restart. Landed from contributor PR #31138 by @Sid-Qin. Thanks @Sid-Qin.
|
||||
- Feishu/Multi-account + reply reliability: add `channels.feishu.defaultAccount` outbound routing support with schema validation, prevent inbound preview text from leaking into prompt system events, keep quoted-message extraction text-first (post/interactive/file placeholders instead of raw JSON), route Feishu video sends as `msg_type: "file"`, and avoid websocket event blocking by using non-blocking event handling in monitor dispatch. Landed from contributor PRs #31209, #29610, #30432, #30331, and #29501. Thanks @stakeswky, @hclsys, @bmendonca3, @patrick-yingxi-pan, and @zwffff.
|
||||
- Feishu/System preview prompt leakage: stop enqueuing inbound Feishu message previews as system events so user preview text is not injected into later turns as trusted `System:` context. Landed from contributor PR #31209 by @stakeswky. Thanks @stakeswky.
|
||||
- Feishu/Multi-account + reply reliability: add `channels.feishu.defaultAccount` outbound routing support with schema validation, keep quoted-message extraction text-first (post/interactive/file placeholders instead of raw JSON), route Feishu video sends as `msg_type: "file"`, and avoid websocket event blocking by using non-blocking event handling in monitor dispatch. Landed from contributor PRs #29610, #30432, #30331, and #29501. Thanks @hclsys, @bmendonca3, @patrick-yingxi-pan, and @zwffff.
|
||||
- Google Chat/Thread replies: set `messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD` on threaded sends so replies attach to existing threads instead of silently failing thread placement. Landed from contributor PR #30965 by @novan. Thanks @novan.
|
||||
- Mattermost/Private channel policy routing: map Mattermost private channel type `P` to group chat type so `groupPolicy`/`groupAllowFrom` gates apply correctly instead of being treated as open public channels. Landed from contributor PR #30891 by @BlueBirdBack. Thanks @BlueBirdBack.
|
||||
- Models/Custom provider keys: trim custom provider map keys during normalization so image-capable models remain discoverable when provider keys are configured with leading/trailing whitespace. Landed from contributor PR #31202 by @stakeswky. Thanks @stakeswky.
|
||||
|
||||
@@ -120,6 +120,7 @@ describe("handleFeishuMessage command authorization", () => {
|
||||
const mockReadAllowFromStore = vi.fn().mockResolvedValue([]);
|
||||
const mockUpsertPairingRequest = vi.fn().mockResolvedValue({ code: "ABCDEFGH", created: false });
|
||||
const mockBuildPairingReply = vi.fn(() => "Pairing response");
|
||||
const mockEnqueueSystemEvent = vi.fn();
|
||||
const mockSaveMediaBuffer = vi.fn().mockResolvedValue({
|
||||
path: "/tmp/inbound-clip.mp4",
|
||||
contentType: "video/mp4",
|
||||
@@ -127,6 +128,7 @@ describe("handleFeishuMessage command authorization", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
mockShouldComputeCommandAuthorized.mockReset().mockReturnValue(true);
|
||||
mockResolveAgentRoute.mockReturnValue({
|
||||
agentId: "main",
|
||||
accountId: "default",
|
||||
@@ -140,9 +142,10 @@ describe("handleFeishuMessage command authorization", () => {
|
||||
},
|
||||
},
|
||||
});
|
||||
mockEnqueueSystemEvent.mockReset();
|
||||
setFeishuRuntime({
|
||||
system: {
|
||||
enqueueSystemEvent: vi.fn(),
|
||||
enqueueSystemEvent: mockEnqueueSystemEvent,
|
||||
},
|
||||
channel: {
|
||||
routing: {
|
||||
@@ -174,6 +177,37 @@ describe("handleFeishuMessage command authorization", () => {
|
||||
} as unknown as PluginRuntime);
|
||||
});
|
||||
|
||||
it("does not enqueue inbound preview text as system events", 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-no-system-preview",
|
||||
chat_id: "oc-dm",
|
||||
chat_type: "p2p",
|
||||
message_type: "text",
|
||||
content: JSON.stringify({ text: "hi there" }),
|
||||
},
|
||||
};
|
||||
|
||||
await dispatchMessage({ cfg, event });
|
||||
|
||||
expect(mockEnqueueSystemEvent).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("uses authorizer resolution instead of hardcoded CommandAuthorized=true", async () => {
|
||||
const cfg: ClawdbotConfig = {
|
||||
commands: { useAccessGroups: true },
|
||||
|
||||
Reference in New Issue
Block a user