Files
openclaw/src/agents/tool-policy.plugin-only-allowlist.test.ts
Agustin Rivera 193fdd6e3b fix(policy): preserve restrictive tool allowlists (#58476)
* fix(policy): preserve restrictive tool allowlists

Co-authored-by: David Silva <david.silva@gendigital.com>

* fix(policy): address review follow-ups

* fix(policy): restore additive alsoAllow semantics

* fix(policy): preserve optional tool opt-ins for allow-all configs

* fix(policy): narrow plugin-only allowlist warnings

* fix(policy): add changelog entry

* Revert "fix(policy): add changelog entry"

This reverts commit 4a996bf4ca.

* chore: add changelog for restrictive tool allowlists

---------

Co-authored-by: David Silva <david.silva@gendigital.com>
Co-authored-by: Devin Robison <drobison@nvidia.com>
2026-04-02 12:55:36 -06:00

83 lines
3.0 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
analyzeAllowlistByToolType,
buildPluginToolGroups,
type PluginToolGroups,
} from "./tool-policy.js";
const pluginGroups: PluginToolGroups = {
all: ["lobster", "workflow_tool"],
byPlugin: new Map([["lobster", ["lobster", "workflow_tool"]]]),
};
const coreTools = new Set(["read", "write", "exec", "session_status"]);
describe("analyzeAllowlistByToolType", () => {
it("preserves allowlist when it only targets plugin tools", () => {
const policy = analyzeAllowlistByToolType({ allow: ["lobster"] }, pluginGroups, coreTools);
expect(policy.policy?.allow).toEqual(["lobster"]);
expect(policy.pluginOnlyAllowlist).toBe(true);
expect(policy.unknownAllowlist).toEqual([]);
});
it("preserves allowlist when it only targets plugin groups", () => {
const policy = analyzeAllowlistByToolType(
{ allow: ["group:plugins"] },
pluginGroups,
coreTools,
);
expect(policy.policy?.allow).toEqual(["group:plugins"]);
expect(policy.pluginOnlyAllowlist).toBe(true);
expect(policy.unknownAllowlist).toEqual([]);
});
it('keeps allowlist when it uses "*"', () => {
const policy = analyzeAllowlistByToolType({ allow: ["*"] }, pluginGroups, coreTools);
expect(policy.policy?.allow).toEqual(["*"]);
expect(policy.unknownAllowlist).toEqual([]);
});
it("keeps allowlist when it mixes plugin and core entries", () => {
const policy = analyzeAllowlistByToolType(
{ allow: ["lobster", "read"] },
pluginGroups,
coreTools,
);
expect(policy.policy?.allow).toEqual(["lobster", "read"]);
expect(policy.unknownAllowlist).toEqual([]);
});
it("preserves allowlist with unknown entries when no core tools match", () => {
const emptyPlugins: PluginToolGroups = { all: [], byPlugin: new Map() };
const policy = analyzeAllowlistByToolType({ allow: ["lobster"] }, emptyPlugins, coreTools);
expect(policy.policy?.allow).toEqual(["lobster"]);
expect(policy.pluginOnlyAllowlist).toBe(false);
expect(policy.unknownAllowlist).toEqual(["lobster"]);
});
it("keeps allowlist with core tools and reports unknown entries", () => {
const emptyPlugins: PluginToolGroups = { all: [], byPlugin: new Map() };
const policy = analyzeAllowlistByToolType(
{ allow: ["read", "lobster"] },
emptyPlugins,
coreTools,
);
expect(policy.policy?.allow).toEqual(["read", "lobster"]);
expect(policy.unknownAllowlist).toEqual(["lobster"]);
});
it("does not mark unavailable core entries as plugin-only", () => {
const policy = analyzeAllowlistByToolType({ allow: ["apply_patch"] }, pluginGroups, coreTools);
expect(policy.pluginOnlyAllowlist).toBe(false);
expect(policy.unknownAllowlist).toEqual(["apply_patch"]);
});
it("ignores empty plugin ids when building groups", () => {
const groups = buildPluginToolGroups({
tools: [{ name: "lobster" }],
toolMeta: () => ({ pluginId: "" }),
});
expect(groups.all).toEqual(["lobster"]);
expect(groups.byPlugin.size).toBe(0);
});
});