From a48274f82b95eb5a2f68d94a1cfa8518cf80c2a7 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Tue, 5 Aug 2025 19:14:28 -0500 Subject: [PATCH] permissions disallow support (#1627) --- packages/opencode/src/config/config.ts | 2 +- packages/opencode/src/session/index.ts | 2 +- packages/opencode/src/tool/bash.ts | 9 ++++++-- packages/opencode/src/tool/registry.ts | 30 +++++++++++++++++--------- 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index b0bea5d3..88fff6bf 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -224,7 +224,7 @@ export namespace Config { }) export type Layout = z.infer - export const Permission = z.union([z.literal("ask"), z.literal("allow")]) + export const Permission = z.union([z.literal("ask"), z.literal("allow"), z.literal("deny")]) export type Permission = z.infer export const Info = z diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts index 89ae5a57..c4d81a8c 100644 --- a/packages/opencode/src/session/index.ts +++ b/packages/opencode/src/session/index.ts @@ -728,7 +728,7 @@ export namespace Session { const enabledTools = pipe( mode.tools, - mergeDeep(ToolRegistry.enabled(input.providerID, input.modelID)), + mergeDeep(await ToolRegistry.enabled(input.providerID, input.modelID)), mergeDeep(input.tools ?? {}), ) for (const item of await ToolRegistry.tools(input.providerID, input.modelID)) { diff --git a/packages/opencode/src/tool/bash.ts b/packages/opencode/src/tool/bash.ts index a4a418d9..de1eedaa 100644 --- a/packages/opencode/src/tool/bash.ts +++ b/packages/opencode/src/tool/bash.ts @@ -93,7 +93,7 @@ export const BashTool = Tool.define("bash", { // always allow cd if it passes above check if (!needsAsk && command[0] !== "cd") { - const ask = (() => { + const action = (() => { for (const [pattern, value] of Object.entries(permissions)) { const match = Wildcard.match(node.text, pattern) log.info("checking", { text: node.text.trim(), pattern, match }) @@ -101,7 +101,12 @@ export const BashTool = Tool.define("bash", { } return "ask" })() - if (ask === "ask") needsAsk = true + if (action === "deny") { + throw new Error( + "The user has specifically restricted access to this command, you are not allowed to execute it.", + ) + } + if (action === "ask") needsAsk = true } } diff --git a/packages/opencode/src/tool/registry.ts b/packages/opencode/src/tool/registry.ts index d3396554..c49dbb00 100644 --- a/packages/opencode/src/tool/registry.ts +++ b/packages/opencode/src/tool/registry.ts @@ -11,6 +11,7 @@ import { TodoWriteTool, TodoReadTool } from "./todo" import { WebFetchTool } from "./webfetch" import { WriteTool } from "./write" import { InvalidTool } from "./invalid" +import { Config } from "../config/config" export namespace ToolRegistry { const ALL = [ @@ -65,11 +66,19 @@ export namespace ToolRegistry { return result } - export function enabled(_providerID: string, modelID: string): Record { + export async function enabled(_providerID: string, modelID: string): Promise> { + const cfg = await Config.get() + const result: Record = {} + + if (cfg.permission?.edit === "deny") { + result["edit"] = false + result["patch"] = false + result["write"] = false + } + if (modelID.toLowerCase().includes("claude")) { - return { - patch: false, - } + result["patch"] = false + return result } if ( @@ -79,13 +88,14 @@ export namespace ToolRegistry { modelID.includes("o3") || modelID.includes("codex") ) { - return { - patch: false, - todowrite: false, - todoread: false, - } + result["patch"] = false + result["todowrite"] = false + result["todoread"] = false + + return result } - return {} + + return result } function sanitizeGeminiParameters(schema: z.ZodTypeAny, visited = new Set()): z.ZodTypeAny {