fix(security): centralize owner-only tool gating and scope maps

This commit is contained in:
Peter Steinberger
2026-02-19 15:27:45 +01:00
parent 9130fd2b06
commit 3d7ad1cfca
16 changed files with 372 additions and 251 deletions

View File

@@ -1,4 +1,4 @@
import { OWNER_ONLY_TOOL_ERROR, type AnyAgentTool } from "./tools/common.js";
import { type AnyAgentTool, wrapOwnerOnlyToolExecution } from "./tools/common.js";
export type ToolProfileId = "minimal" | "coding" | "messaging" | "full";
@@ -60,7 +60,7 @@ export const TOOL_GROUPS: Record<string, string[]> = {
],
};
const OWNER_ONLY_TOOL_NAMES = new Set<string>(["whatsapp_login", "cron", "gateway"]);
const OWNER_ONLY_TOOL_NAME_FALLBACKS = new Set<string>(["whatsapp_login", "cron", "gateway"]);
const TOOL_PROFILES: Record<ToolProfileId, ToolProfilePolicy> = {
minimal: {
@@ -87,28 +87,24 @@ export function normalizeToolName(name: string) {
}
export function isOwnerOnlyToolName(name: string) {
return OWNER_ONLY_TOOL_NAMES.has(normalizeToolName(name));
return OWNER_ONLY_TOOL_NAME_FALLBACKS.has(normalizeToolName(name));
}
function isOwnerOnlyTool(tool: AnyAgentTool) {
return tool.ownerOnly === true || isOwnerOnlyToolName(tool.name);
}
export function applyOwnerOnlyToolPolicy(tools: AnyAgentTool[], senderIsOwner: boolean) {
const withGuard = tools.map((tool) => {
if (!isOwnerOnlyToolName(tool.name)) {
if (!isOwnerOnlyTool(tool)) {
return tool;
}
if (senderIsOwner || !tool.execute) {
return tool;
}
return {
...tool,
execute: async () => {
throw new Error(OWNER_ONLY_TOOL_ERROR);
},
};
return wrapOwnerOnlyToolExecution(tool, senderIsOwner);
});
if (senderIsOwner) {
return withGuard;
}
return withGuard.filter((tool) => !isOwnerOnlyToolName(tool.name));
return withGuard.filter((tool) => !isOwnerOnlyTool(tool));
}
export function normalizeToolList(list?: string[]) {