fix(acp): harden permission auto-approval policy

This commit is contained in:
Peter Steinberger
2026-02-24 01:03:12 +00:00
parent ddf93d9845
commit 12cc754332
5 changed files with 179 additions and 49 deletions

View File

@@ -74,6 +74,32 @@ describe("resolvePermissionRequest", () => {
expect(prompt).not.toHaveBeenCalled();
});
it("prompts for read outside cwd scope", async () => {
const prompt = vi.fn(async () => false);
const res = await resolvePermissionRequest(
makePermissionRequest({
toolCall: { toolCallId: "tool-r", title: "read: ~/.ssh/id_rsa", status: "pending" },
}),
{ prompt, log: () => {} },
);
expect(prompt).toHaveBeenCalledTimes(1);
expect(prompt).toHaveBeenCalledWith("read", "read: ~/.ssh/id_rsa");
expect(res).toEqual({ outcome: { outcome: "selected", optionId: "reject" } });
});
it("prompts for non-core read-like tool names", async () => {
const prompt = vi.fn(async () => false);
const res = await resolvePermissionRequest(
makePermissionRequest({
toolCall: { toolCallId: "tool-fr", title: "fs_read: ~/.ssh/id_rsa", status: "pending" },
}),
{ prompt, log: () => {} },
);
expect(prompt).toHaveBeenCalledTimes(1);
expect(prompt).toHaveBeenCalledWith("fs_read", "fs_read: ~/.ssh/id_rsa");
expect(res).toEqual({ outcome: { outcome: "selected", optionId: "reject" } });
});
it.each([
{
caseName: "prompts for fetch even when tool name is known",
@@ -100,6 +126,24 @@ describe("resolvePermissionRequest", () => {
expect(res).toEqual({ outcome: { outcome: "selected", optionId: "reject" } });
});
it("prompts when kind is spoofed as read", async () => {
const prompt = vi.fn(async () => false);
const res = await resolvePermissionRequest(
makePermissionRequest({
toolCall: {
toolCallId: "tool-kind-spoof",
title: "thread: reply",
status: "pending",
kind: "read",
},
}),
{ prompt, log: () => {} },
);
expect(prompt).toHaveBeenCalledTimes(1);
expect(prompt).toHaveBeenCalledWith("thread", "thread: reply");
expect(res).toEqual({ outcome: { outcome: "selected", optionId: "reject" } });
});
it("uses allow_always and reject_always when once options are absent", async () => {
const options: RequestPermissionRequest["options"] = [
{ kind: "allow_always", name: "Always allow", optionId: "allow-always" },