chore: cleanup external_dir perm logic (#11845)

This commit is contained in:
Aiden Cline
2026-02-02 16:43:55 -06:00
committed by GitHub
parent 5e3162b7f4
commit 188cc24bfc
4 changed files with 53 additions and 16 deletions

View File

@@ -447,7 +447,7 @@ test("legacy tools config maps write/edit/patch/multiedit to edit permission", a
})
})
test("Truncate.DIR is allowed even when user denies external_directory globally", async () => {
test("Truncate.GLOB is allowed even when user denies external_directory globally", async () => {
const { Truncate } = await import("../../src/tool/truncation")
await using tmp = await tmpdir({
config: {
@@ -460,14 +460,14 @@ test("Truncate.DIR is allowed even when user denies external_directory globally"
directory: tmp.path,
fn: async () => {
const build = await Agent.get("build")
expect(PermissionNext.evaluate("external_directory", Truncate.DIR, build!.permission).action).toBe("allow")
expect(PermissionNext.evaluate("external_directory", Truncate.GLOB, build!.permission).action).toBe("allow")
expect(PermissionNext.evaluate("external_directory", Truncate.DIR, build!.permission).action).toBe("deny")
expect(PermissionNext.evaluate("external_directory", "/some/other/path", build!.permission).action).toBe("deny")
},
})
})
test("Truncate.DIR is allowed even when user denies external_directory per-agent", async () => {
test("Truncate.GLOB is allowed even when user denies external_directory per-agent", async () => {
const { Truncate } = await import("../../src/tool/truncation")
await using tmp = await tmpdir({
config: {
@@ -484,21 +484,21 @@ test("Truncate.DIR is allowed even when user denies external_directory per-agent
directory: tmp.path,
fn: async () => {
const build = await Agent.get("build")
expect(PermissionNext.evaluate("external_directory", Truncate.DIR, build!.permission).action).toBe("allow")
expect(PermissionNext.evaluate("external_directory", Truncate.GLOB, build!.permission).action).toBe("allow")
expect(PermissionNext.evaluate("external_directory", Truncate.DIR, build!.permission).action).toBe("deny")
expect(PermissionNext.evaluate("external_directory", "/some/other/path", build!.permission).action).toBe("deny")
},
})
})
test("explicit Truncate.DIR deny is respected", async () => {
test("explicit Truncate.GLOB deny is respected", async () => {
const { Truncate } = await import("../../src/tool/truncation")
await using tmp = await tmpdir({
config: {
permission: {
external_directory: {
"*": "deny",
[Truncate.DIR]: "deny",
[Truncate.GLOB]: "deny",
},
},
},
@@ -507,8 +507,8 @@ test("explicit Truncate.DIR deny is respected", async () => {
directory: tmp.path,
fn: async () => {
const build = await Agent.get("build")
expect(PermissionNext.evaluate("external_directory", Truncate.DIR, build!.permission).action).toBe("deny")
expect(PermissionNext.evaluate("external_directory", Truncate.GLOB, build!.permission).action).toBe("deny")
expect(PermissionNext.evaluate("external_directory", Truncate.DIR, build!.permission).action).toBe("deny")
},
})
})

View File

@@ -144,7 +144,42 @@ describe("tool.bash permissions", () => {
)
const extDirReq = requests.find((r) => r.permission === "external_directory")
expect(extDirReq).toBeDefined()
expect(extDirReq!.patterns).toContain("/tmp")
expect(extDirReq!.patterns).toContain("/tmp/*")
},
})
})
test("asks for external_directory permission when file arg is outside project", async () => {
await using outerTmp = await tmpdir({
init: async (dir) => {
await Bun.write(path.join(dir, "outside.txt"), "x")
},
})
await using tmp = await tmpdir({ git: true })
await Instance.provide({
directory: tmp.path,
fn: async () => {
const bash = await BashTool.init()
const requests: Array<Omit<PermissionNext.Request, "id" | "sessionID" | "tool">> = []
const testCtx = {
...ctx,
ask: async (req: Omit<PermissionNext.Request, "id" | "sessionID" | "tool">) => {
requests.push(req)
},
}
const filepath = path.join(outerTmp.path, "outside.txt")
await bash.execute(
{
command: `cat ${filepath}`,
description: "Read external file",
},
testCtx,
)
const extDirReq = requests.find((r) => r.permission === "external_directory")
const expected = path.join(outerTmp.path, "*")
expect(extDirReq).toBeDefined()
expect(extDirReq!.patterns).toContain(expected)
expect(extDirReq!.always).toContain(expected)
},
})
})