mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-11 03:34:33 +00:00
security(feishu): bind doc create grants to trusted requester context (#31184)
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
This commit is contained in:
28
src/agents/openclaw-tools.plugin-context.test.ts
Normal file
28
src/agents/openclaw-tools.plugin-context.test.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
const resolvePluginToolsMock = vi.fn(() => []);
|
||||
|
||||
vi.mock("../plugins/tools.js", () => ({
|
||||
resolvePluginTools: (params: unknown) => resolvePluginToolsMock(params),
|
||||
}));
|
||||
|
||||
import { createOpenClawTools } from "./openclaw-tools.js";
|
||||
|
||||
describe("createOpenClawTools plugin context", () => {
|
||||
it("forwards trusted requester sender identity to plugin tool context", () => {
|
||||
createOpenClawTools({
|
||||
config: {} as never,
|
||||
requesterSenderId: "trusted-sender",
|
||||
senderIsOwner: true,
|
||||
});
|
||||
|
||||
expect(resolvePluginToolsMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
context: expect.objectContaining({
|
||||
requesterSenderId: "trusted-sender",
|
||||
senderIsOwner: true,
|
||||
}),
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -187,6 +187,8 @@ export function createOpenClawTools(options?: {
|
||||
sessionKey: options?.agentSessionKey,
|
||||
messageChannel: options?.agentChannel,
|
||||
agentAccountId: options?.agentAccountId,
|
||||
requesterSenderId: options?.requesterSenderId ?? undefined,
|
||||
senderIsOwner: options?.senderIsOwner ?? undefined,
|
||||
sandboxed: options?.sandboxed,
|
||||
},
|
||||
existingToolNames: new Set(tools.map((tool) => tool.name)),
|
||||
|
||||
@@ -63,6 +63,10 @@ export type OpenClawPluginToolContext = {
|
||||
sessionKey?: string;
|
||||
messageChannel?: string;
|
||||
agentAccountId?: string;
|
||||
/** Trusted sender id from inbound context (runtime-provided, not tool args). */
|
||||
requesterSenderId?: string;
|
||||
/** Whether the trusted sender is an owner. */
|
||||
senderIsOwner?: boolean;
|
||||
sandboxed?: boolean;
|
||||
};
|
||||
|
||||
|
||||
@@ -1266,7 +1266,7 @@ describe("security audit", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("warns when Feishu doc tool is enabled because create supports owner_open_id", async () => {
|
||||
it("warns when Feishu doc tool is enabled because create can grant requester access", async () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
channels: {
|
||||
feishu: {
|
||||
@@ -1280,7 +1280,7 @@ describe("security audit", () => {
|
||||
expectFinding(res, "channels.feishu.doc_owner_open_id", "warn");
|
||||
});
|
||||
|
||||
it("does not warn for Feishu owner_open_id when doc tools are disabled", async () => {
|
||||
it("does not warn for Feishu doc grant risk when doc tools are disabled", async () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
channels: {
|
||||
feishu: {
|
||||
|
||||
@@ -519,11 +519,11 @@ function collectGatewayConfigFindings(
|
||||
findings.push({
|
||||
checkId: "channels.feishu.doc_owner_open_id",
|
||||
severity: "warn",
|
||||
title: "Feishu doc create can grant owner permissions",
|
||||
title: "Feishu doc create can grant requester permissions",
|
||||
detail:
|
||||
'channels.feishu tools include "doc"; feishu_doc action "create" accepts owner_open_id and can grant document access to that user.',
|
||||
'channels.feishu tools include "doc"; feishu_doc action "create" can grant document access to the trusted requesting Feishu user.',
|
||||
remediation:
|
||||
"Disable channels.feishu.tools.doc when not needed, and restrict tool access so untrusted prompts cannot set owner_open_id.",
|
||||
"Disable channels.feishu.tools.doc when not needed, and restrict tool access for untrusted prompts.",
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user