Repository navigation
Description
Summary
A session whose agent denies edit (e.g. the plan primary agent) can silently escalate to full write access by delegating work to the general subagent. The child session runs with its own permission policy, which allows edits, so files that the parent agent is forbidden to touch get written anyway. This broke the trust model of plan mode in a real session: the parent had every write denied, while a delegated child modified 12 tracked files.
Environment
- opencode version: v2.0.26 (
opencode --version) - OS: Microsoft Windows NT 10.0.26300.0 (X64), win32
- Terminal: Unavailable: TERM=xterm-256color, TERM_PROGRAM unset, WT_SESSION unset
- Shell: C:\WINDOWS\system32\cmd.exe (session ran PowerShell 7.6.6)
- Install/channel: release
- Active plugins: superpowers (git+https://github.com/obra/superpowers.git), @cortexkit/opencode-magic-context, @cortexkit/aft-opencode@latest, @dietrichgebert/ponytail, cc-safety-net, @bastiangx/opencode-unmoji@latest
Reproduction
- Start a session that uses the
planprimary agent, whose shipped policy denies edits except files under~/.opencode/plan. - Ask the agent to implement a code change.
- The parent agent calls the
subagenttool withagent: "general"and an implementation prompt. - The child session applies edits and returns a success report.
- In the same session, the parent's own
write/editcalls still returnpermission_denied: edit is denied by this session's permission rules.
Minimal shape: any prompt that makes a read-only primary agent delegate implementation work to general.
Expected Behavior
The subagent tool should not let a child acquire permissions the parent session does not have. One of:
- The child inherits the parent session's effective permission policy (parent denies edit, child denies edit), or
- The first child write triggers an approval in the parent session, or
- The
subagenttool refuses to launch, or warns before launching, a write-capable agent from a session whose agent deniesedit.
At minimum the behavior should be visible to the user: the operator had no indication that delegating from plan mode would produce real file writes.
Actual Behavior
The parent session's write tool returned a hard permission denial:
write D:\Tida\psi_parse_tmp.py
permission_denied: edit is denied by this session's permission rules (not a user choice)
The general child, launched moments later with an implementation prompt, wrote 12 tracked files in the same repository without any approval prompt:
M CONTEXT.md
M docs/agents/article-tools.md
M docs/agents/domain.md
M src/components/AiSummary.astro
M src/components/Header.astro
M src/components/tools/MissingTeethRisk.astro
M src/pages/mag/[...slug].astro
M tests/a11y-css.test.ts
M tests/advisor-guards.test.ts
M tests/ai-summary.test.ts
M tests/rendering.test.ts
M tests/tool-components.test.ts
The child then reported npm run verify exiting 0, i.e. the writes were fully committed to the working tree.
No user-facing warning, prompt, or confirmation appeared for the child writes. The operator discovered the escalation only by noticing the git status.
Additional Context
This matches documented behavior, which is what makes it a trust-model gap rather than a straightforward bug:
- https://opencode.ai/v2/docs/agents: "Subagents run with fresh context in foreground or background child sessions. The parent agent's
subagentpermissions control which agents it may launch; the child uses its own configured permissions." - https://opencode.ai/v2/docs/permissions: "A custom subagent uses its own permissions, not a subset of its parent's permissions." The shipped
generalpolicy only "denies questions and launching subagents", so it inherits the base{ action: "*", resource: "*", effect: "allow" }rule foredit.
So a plan session is read-only only until it delegates. Since delegation to general is the primary multi-step workflow, the practical effect is that plan mode can be bypassed by any task phrased as "delegate this to a subagent".
Two concrete requests:
- Document the escalation in the agents/permissions guides, since the current wording ("the child uses its own configured permissions") is easy to read as sandboxing when it is the opposite.
- Consider an inheritance or approval gate so a parent that cannot write cannot spawn a writer.
Frequency: reproducible on demand, not intermittent. Workaround: manually run the subagent with an implementation prompt only after explicitly leaving plan mode.
Unrelated note for the reporter's repo, not part of this issue: the same machine carries a second, untracked project inside the working tree that Tailwind auto-content-detection scans, leaking style rules into the first project's build output. Filing separately if wanted.
Activity
opencode-agent commentedon Oct 15, 2026
Thanks for the detailed write-up. You're asking for two things: (1) the agents and permissions docs should make it clear that a subagent can have more permissions than its parent, and (2) a read-only session such as
planshouldn't be able to gain write access by delegating, whether through inherited denies, an approval in the parent, or a refusal or warning before launching a write-capable agent. Maintainers will consider it.You're right that this is how it currently works. The shipped
planagent deniesedit, but it doesn't denysubagent. Only its system reminder tells the model not to ask a subagent to modify files, and the model can ignore that.planalso doesn't denyshell, so it isn't a strict sandbox even without subagents.In the meantime you can enforce this yourself. Deny subagents for
planbut keep the read-onlyexploreagent:{ "$schema": "https://opencode.ai/config.json", "agents": { "plan": { "permissions": [ { "action": "subagent", "resource": "*", "effect": "deny" }, { "action": "subagent", "resource": "explore", "effect": "allow" }, { "action": "shell", "resource": "*", "effect": "ask" } ] } } }(The
shellrule is optional. It makes shell commands from plan mode need your approval.)Related issues:
Project579 commentedon Nov 8, 2026
This also affects custom agents, not only Plan, and I think it is a v1 → v2 regression.
Repro (2.2.5 and dev 3ce4ca4):
"permissions": [{ "action": "*", "resource": "*", "effect": "allow" }]."agents": { "readonly": { "mode": "primary", "system": "Delegate every request to the general subagent.", "permissions": [{ "action": "edit", "resource": "*", "effect": "deny" }] } }Expected: the subagent's edit is denied, as the parent's would be.
Actual: the
generalsubagent's edit succeeds and README.md changes.Cause: a child session copies only the parent session's rules (
packages/core/src/session.ts:314). Permission checks then use the child's own agent and session rules (packages/core/src/permission.ts,configured). The parent agent's rules, where Plan's edit deny lives, are never checked. Plan's only guard is a prompt line.v1 had this fixed: #26597 (subagents inherit the parent agent's denies), narrowed by #27201 (only
editdenies, so a restricted controller can still delegate), and #30610 (nested subagents). v2 has no equivalent. Restoring the #27201 behaviour would fix this issue.