Merge f0d03344658377a427b56888df623675cda26342 into 598f1826d8b2bc969aace2c6459824737667218c
This commit is contained in:
commit
2138bcc4a8
@ -271,4 +271,76 @@ describe("resolveEffectiveToolPolicy", () => {
|
||||
const result = resolveEffectiveToolPolicy({ config: cfg, agentId: "coder" });
|
||||
expect(result.profileAlsoAllow).toEqual(["read", "write", "edit"]);
|
||||
});
|
||||
|
||||
it("does not implicitly expose global exec when agent has explicit alsoAllow without it", () => {
|
||||
// Regression test for #47487: tool profile restrictions not enforced
|
||||
const cfg = {
|
||||
tools: {
|
||||
exec: { security: "full", ask: "off" },
|
||||
},
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "messenger",
|
||||
tools: {
|
||||
profile: "messaging",
|
||||
alsoAllow: ["web_search"],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
const result = resolveEffectiveToolPolicy({ config: cfg, agentId: "messenger" });
|
||||
expect(result.profileAlsoAllow).toEqual(["web_search"]);
|
||||
expect(result.profileAlsoAllow).not.toContain("exec");
|
||||
expect(result.profileAlsoAllow).not.toContain("process");
|
||||
});
|
||||
|
||||
it("does not implicitly expose global fs when agent has explicit empty alsoAllow", () => {
|
||||
const cfg = {
|
||||
tools: {
|
||||
fs: { workspaceOnly: false },
|
||||
},
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "restricted",
|
||||
tools: {
|
||||
profile: "messaging",
|
||||
alsoAllow: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
const result = resolveEffectiveToolPolicy({ config: cfg, agentId: "restricted" });
|
||||
// Empty array is returned (not undefined) when explicit alsoAllow is set
|
||||
expect(result.profileAlsoAllow).toEqual([]);
|
||||
expect(result.profileAlsoAllow).not.toContain("read");
|
||||
expect(result.profileAlsoAllow).not.toContain("write");
|
||||
expect(result.profileAlsoAllow).not.toContain("edit");
|
||||
});
|
||||
|
||||
it("still uses agent-level exec section for implicit exposure even with explicit alsoAllow", () => {
|
||||
const cfg = {
|
||||
tools: {
|
||||
profile: "messaging",
|
||||
},
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "coder",
|
||||
tools: {
|
||||
alsoAllow: ["web_search"],
|
||||
exec: { host: "sandbox" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
const result = resolveEffectiveToolPolicy({ config: cfg, agentId: "coder" });
|
||||
expect(result.profileAlsoAllow).toContain("web_search");
|
||||
expect(result.profileAlsoAllow).toContain("exec");
|
||||
expect(result.profileAlsoAllow).toContain("process");
|
||||
});
|
||||
});
|
||||
|
||||
@ -210,18 +210,25 @@ function hasExplicitToolSection(section: unknown): boolean {
|
||||
function resolveImplicitProfileAlsoAllow(params: {
|
||||
globalTools?: OpenClawConfig["tools"];
|
||||
agentTools?: AgentToolsConfig;
|
||||
/** When agent has explicit alsoAllow, skip global tool sections for implicit exposure. */
|
||||
agentHasExplicitAlsoAllow?: boolean;
|
||||
}): string[] | undefined {
|
||||
const implicit = new Set<string>();
|
||||
// When agent has explicit alsoAllow set, only agent-level tool sections should
|
||||
// trigger implicit exposure. Global tool sections should not override agent's
|
||||
// explicit restriction. This prevents tools.exec at global level from bypassing
|
||||
// an agent's profile + alsoAllow restriction.
|
||||
const useGlobalSections = !params.agentHasExplicitAlsoAllow;
|
||||
if (
|
||||
hasExplicitToolSection(params.agentTools?.exec) ||
|
||||
hasExplicitToolSection(params.globalTools?.exec)
|
||||
(useGlobalSections && hasExplicitToolSection(params.globalTools?.exec))
|
||||
) {
|
||||
implicit.add("exec");
|
||||
implicit.add("process");
|
||||
}
|
||||
if (
|
||||
hasExplicitToolSection(params.agentTools?.fs) ||
|
||||
hasExplicitToolSection(params.globalTools?.fs)
|
||||
(useGlobalSections && hasExplicitToolSection(params.globalTools?.fs))
|
||||
) {
|
||||
implicit.add("read");
|
||||
implicit.add("write");
|
||||
@ -260,9 +267,14 @@ export function resolveEffectiveToolPolicy(params: {
|
||||
modelProvider: params.modelProvider,
|
||||
modelId: params.modelId,
|
||||
});
|
||||
const agentExplicitAlsoAllow = resolveExplicitProfileAlsoAllow(agentTools);
|
||||
const explicitProfileAlsoAllow =
|
||||
resolveExplicitProfileAlsoAllow(agentTools) ?? resolveExplicitProfileAlsoAllow(globalTools);
|
||||
const implicitProfileAlsoAllow = resolveImplicitProfileAlsoAllow({ globalTools, agentTools });
|
||||
agentExplicitAlsoAllow ?? resolveExplicitProfileAlsoAllow(globalTools);
|
||||
const implicitProfileAlsoAllow = resolveImplicitProfileAlsoAllow({
|
||||
globalTools,
|
||||
agentTools,
|
||||
agentHasExplicitAlsoAllow: agentExplicitAlsoAllow !== undefined,
|
||||
});
|
||||
const profileAlsoAllow =
|
||||
explicitProfileAlsoAllow || implicitProfileAlsoAllow
|
||||
? Array.from(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user