Legacy apply_patch permission rules stop matching after config migration

Open Beginner friendly
#50,183 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
85/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
typescript
Domain
authorization

Research direction

Start in packages/core/src/v1/config/migrate.ts at normalizeAction, then compare its output with the edit assertion in packages/core/src/tool/plugin/patch.ts. Run ConfigNormalize.normalize and Permission.evaluate using the reproduction objects. Done means apply_patch permission and tools rules normalize to the edit action and the deny is enforced.

Written by the indexing model from the issue text.

Description

Description

normalizeAction in packages/core/src/v1/config/migrate.ts maps the tool names people write in config onto the permission actions v2 tools actually assert: write/patchedit, tasksubagent, bashshell. apply_patch is missing from the table.

So { "permission": { "apply_patch": "deny" } } normalizes to a rule whose action is apply_patch. Nothing asserts that action — packages/core/src/tool/plugin/patch.ts calls permission.assert with action: "edit" — and unmapped keys produce no diagnostic, so the deny is silently inert. Same for { "tools": { "apply_patch": false } }.

The name is legitimately part of the edit family: agents.mdx lists write, edit, apply_patch under the edit permission, tools.mdx does the same in its apply_patch section, and the TUI (packages/tui/src/util/tool-display.ts) and ACP (packages/cli/src/acp/tool.ts) still canonicalize apply_patch.

Plugins

None

OpenCode version

v2 at 1ca8f63a7

Steps to reproduce

Call ConfigNormalize.normalize on each object and print encoded.permissions:

{"permission":{"write":"deny"}}        -> [{"action":"edit","resource":"*","effect":"deny"}]
{"permission":{"apply_patch":"deny"}}  -> [{"action":"apply_patch","resource":"*","effect":"deny"}]

Permission.evaluate("edit", path, rules) returns deny for the first and passes the second.

Related history: #16028 reported this mapping gap on the v1 codebase, and #16051 proposed the same one-line alias there; both are closed, and #16051 was not merged. Also worth deciding together: #47352 proposes documenting that a write block "is never consulted", but write does get consulted because normalizeAction rewrites it to edit.

Screenshot and/or share link

No response

Operating System

macOS (Apple Silicon)

Terminal

Not a runtime UI issue.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
Avg merge
7h 20m
Merged PRs (30d)
358

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from anomalyco/opencode

All issues in anomalyco/opencode

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.