Skip to content

write permission rules are silently ignored — write.ts asks under edit #40150

Description

@iceteaSA

Description

A write: block in opencode.json or in agent frontmatter parses without error, loads into the ruleset, and is never consulted by anything.

write is not a declared permission key. packages/core/src/v1/config/permission.ts:18-34 declares:

read · edit · glob · grep · list · bash · task · external_directory
todowrite · question · webfetch · websearch · lsp · doom_loop · skill

The struct has a Schema.Record(Schema.String, Rule) rest element, so any unknown key parses cleanly and is carried into the ruleset by fromConfig. Nothing then asks under it.

The write tool asks under edit:

// packages/opencode/src/tool/write.ts:55-57
yield* ctx.ask({
  permission: "edit",
  patterns: [path.relative(instance.worktree, filepath)],

There is no permission: "write" anywhere in src.

The practical effect is that a config like this does not do what it reads as:

{
  "permission": {
    "edit": { "*": "allow" },
    "write": { "*.env": "deny" }
  }
}

The write block is inert; writes are governed entirely by the edit rules. An operator who tightens write and leaves edit open has not tightened anything.

This also means unknown keys generally are silent no-ops — a typo like edt: or bahs: parses, loads, and does nothing, with no warning at any level.

Steps to reproduce

  1. Configure "permission": { "edit": { "*": "allow" }, "write": { "*": "deny" } }.
  2. Have the agent write a file.
  3. The write is allowed. The write deny never participates.
  4. Nothing is logged about the unused key.

The evaluated log line at permission/index.ts:74 confirms it directly: writes appear as permission=edit, and permission=write never appears at all. An independent deployment checked 125,800 evaluated lines and found zero permission=write entries.

OpenCode version

dev @ 1882c33

Expected

One of:

  1. Reject unknown permission keys at parse time. Preferred — it makes this class of mistake loud, and it catches typos as a side effect. It is a breaking change for any config carrying an undeclared key, so it wants a release note.
  2. Make write.ts ask under permission: "write" and document the key. Existing write: blocks become live as written, which is what their authors intended, but anyone relying on edit rules covering writes would see a behaviour change.

Either way write should appear in docs/permissions.mdx — as a supported key, or in the list of keys that do not exist.

Notes

Found while working on #30551 / #40149 (absolute permission patterns not matching outside the worktree). Filed separately because the fixes are unrelated: that one changes which path is matched, this one changes which key is consulted.

Two deployments were carrying write: blocks written in good faith that had never done anything.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions