summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAiden Cline <[email protected]>2025-08-05 19:14:28 -0500
committerGitHub <[email protected]>2025-08-05 19:14:28 -0500
commita48274f82b95eb5a2f68d94a1cfa8518cf80c2a7 (patch)
tree5c4894cec66f1d1b2cb8efd32611d03ccce55fae
parent6b25b7e95ea68321df73e22d62ad33e11154db85 (diff)
downloadopencode-a48274f82b95eb5a2f68d94a1cfa8518cf80c2a7.tar.gz
opencode-a48274f82b95eb5a2f68d94a1cfa8518cf80c2a7.zip
permissions disallow support (#1627)
-rw-r--r--packages/opencode/src/config/config.ts2
-rw-r--r--packages/opencode/src/session/index.ts2
-rw-r--r--packages/opencode/src/tool/bash.ts9
-rw-r--r--packages/opencode/src/tool/registry.ts30
4 files changed, 29 insertions, 14 deletions
diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts
index b0bea5d32..88fff6bf1 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<typeof Layout>
- 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<typeof Permission>
export const Info = z
diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts
index 89ae5a573..c4d81a8c3 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 a4a418d92..de1eedaa8 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 d33965546..c49dbb005 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<string, boolean> {
+ export async function enabled(_providerID: string, modelID: string): Promise<Record<string, boolean>> {
+ const cfg = await Config.get()
+ const result: Record<string, boolean> = {}
+
+ 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 {