From e88b659545245888ee4091a0cc353f4d7bda7327 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Fri, 24 Oct 2025 14:40:36 -0500 Subject: [PATCH] make plan agent whitelist more conservative (#3424) --- packages/opencode/src/agent/agent.ts | 6 --- packages/opencode/test/util/wildcard.test.ts | 55 ++++++++++++++++++++ 2 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 packages/opencode/test/util/wildcard.test.ts diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index 88e52aad..3577a917 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -52,9 +52,6 @@ export namespace Agent { { edit: "deny", bash: { - "awk -i inplace*": "ask", - "awk --inplace*": "ask", - "awk*": "allow", "cut*": "allow", "diff*": "allow", "du*": "allow", @@ -79,9 +76,6 @@ export namespace Agent { "more*": "allow", "pwd*": "allow", "rg*": "allow", - "sed --in-place*": "ask", - "sed -i*": "ask", - "sed -n *": "allow", "sort --output=*": "ask", "sort -o *": "ask", "sort*": "allow", diff --git a/packages/opencode/test/util/wildcard.test.ts b/packages/opencode/test/util/wildcard.test.ts new file mode 100644 index 00000000..f7f1e154 --- /dev/null +++ b/packages/opencode/test/util/wildcard.test.ts @@ -0,0 +1,55 @@ +import { test, expect } from "bun:test" +import { Wildcard } from "../../src/util/wildcard" + +test("match handles glob tokens", () => { + expect(Wildcard.match("file1.txt", "file?.txt")).toBe(true) + expect(Wildcard.match("file12.txt", "file?.txt")).toBe(false) + expect(Wildcard.match("foo+bar", "foo+bar")).toBe(true) +}) + +test("all picks the most specific pattern", () => { + const rules = { + "*": "deny", + "git *": "ask", + "git status": "allow", + } + expect(Wildcard.all("git status", rules)).toBe("allow") + expect(Wildcard.all("git log", rules)).toBe("ask") + expect(Wildcard.all("echo hi", rules)).toBe("deny") +}) + +test("allStructured matches command sequences", () => { + const rules = { + "git *": "ask", + "git status*": "allow", + } + expect(Wildcard.allStructured({ head: "git", tail: ["status", "--short"] }, rules)).toBe("allow") + expect(Wildcard.allStructured({ head: "npm", tail: ["run", "build", "--watch"] }, { "npm run *": "allow" })).toBe( + "allow", + ) + expect(Wildcard.allStructured({ head: "ls", tail: ["-la"] }, rules)).toBeUndefined() +}) + +test("allStructured prioritizes flag-specific patterns", () => { + const rules = { + "find *": "allow", + "find * -delete*": "ask", + "sort*": "allow", + "sort -o *": "ask", + } + expect(Wildcard.allStructured({ head: "find", tail: ["src", "-delete"] }, rules)).toBe("ask") + expect(Wildcard.allStructured({ head: "find", tail: ["src", "-print"] }, rules)).toBe("allow") + expect(Wildcard.allStructured({ head: "sort", tail: ["-o", "out.txt"] }, rules)).toBe("ask") + expect(Wildcard.allStructured({ head: "sort", tail: ["--reverse"] }, rules)).toBe("allow") +}) + +test("allStructured handles sed flags", () => { + const rules = { + "sed * -i*": "ask", + "sed -n*": "allow", + } + expect(Wildcard.allStructured({ head: "sed", tail: ["-i", "file"] }, rules)).toBe("ask") + expect(Wildcard.allStructured({ head: "sed", tail: ["-i.bak", "file"] }, rules)).toBe("ask") + expect(Wildcard.allStructured({ head: "sed", tail: ["-n", "1p", "file"] }, rules)).toBe("allow") + expect(Wildcard.allStructured({ head: "sed", tail: ["-i", "-n", "/./p", "myfile.txt"] }, rules)).toBe("ask") +})