Description
read permission patterns are evaluated against the absolute file path, while edit / write / apply_patch patterns are evaluated against the path relative to the worktree. A user rule like "read": { "src/*": "deny" } therefore silently fails to match, even though the equivalent "edit": { "src/*": "deny" } works.
Root cause is in packages/opencode/src/tool/read.ts:181: patterns: [filepath] (absolute), versus path.relative(instance.worktree, filePath) that the other file tools use.
Related: #20307, #20045, #11059, #22465.
Plugins
None
OpenCode version
dev (current)
Steps to reproduce
-
In any project, set opencode.json:
{
"permission": {
"read": { "*": "allow", "src/*": "deny" },
"edit": { "*": "allow", "src/*": "deny" }
}
}
-
Ask the agent to edit src/foo.ts → "src/*" matches the worktree-relative src/foo.ts → denied (correct).
-
Ask the agent to read src/foo.ts → "src/*" is matched against the absolute /abs/path/.../src/foo.ts → does NOT match → falls back to "*": "allow" → read goes through anyway (bug).
Same rule, same file, different outcome — purely because of the absolute-vs-relative pattern asymmetry.
Operating System
Any
Terminal
Any
Description
readpermission patterns are evaluated against the absolute file path, whileedit/write/apply_patchpatterns are evaluated against the path relative to the worktree. A user rule like"read": { "src/*": "deny" }therefore silently fails to match, even though the equivalent"edit": { "src/*": "deny" }works.Root cause is in
packages/opencode/src/tool/read.ts:181:patterns: [filepath](absolute), versuspath.relative(instance.worktree, filePath)that the other file tools use.Related: #20307, #20045, #11059, #22465.
Plugins
None
OpenCode version
dev (current)
Steps to reproduce
In any project, set
opencode.json:{ "permission": { "read": { "*": "allow", "src/*": "deny" }, "edit": { "*": "allow", "src/*": "deny" } } }Ask the agent to edit
src/foo.ts→"src/*"matches the worktree-relativesrc/foo.ts→ denied (correct).Ask the agent to read
src/foo.ts→"src/*"is matched against the absolute/abs/path/.../src/foo.ts→ does NOT match → falls back to"*": "allow"→ read goes through anyway (bug).Same rule, same file, different outcome — purely because of the absolute-vs-relative pattern asymmetry.
Operating System
Any
Terminal
Any