Skip to content

Subagent permission rules are ignored, hence deny rules never applied #33223

Closed as not planned

Description

@sesigl

Description

Subagent permission rules defined in agent config are silently ignored. The subagent session never receives them.

The root cause is in deriveSubagentSessionPermission at packages/opencode/src/agent/subagent-permissions.ts. It reads input.subagent.permission (the agent's configured ruleset) only to check for task/todowrite entries. It never includes the subagent's own rules in the returned permission array.

export function deriveSubagentSessionPermission(input: { ... }): PermissionV1.Ruleset {
  const canTask = input.subagent.permission.some(...)
  const canTodo = input.subagent.permission.some(...)
  return [
    ...input.parentSessionPermission.filter(
      (rule) => rule.permission === "external_directory" || rule.action === "deny",
    ),
    ...(canTodo ? [] : [{ permission: "todowrite", pattern: "*", action: "deny" }]),
    ...(canTask ? [] : [{ permission: "task", pattern: "*", action: "deny" }]),
    // input.subagent.permission never used in output
  ]
}

The subagent session ends up with only parent deny rules + default task/todowrite denies. The agent's own read, glob, grep, list deny rules are dropped.

Steps to reproduce

  1. Create a subagent with deny rules in permission.read etc.
  2. Launch it via the task tool
  3. Ask it to read a file under the denied path

The subagent can read the file — the deny rules are not enforced.

OpenCode version

1.17.8

OS

macOS Sequoia 15

Activity

  1. changed the title [-]Subagent permission rules are ignored — deny rules never applied[/-] [+]Subagent permission rules are ignored, hence deny rules never applied[/+] on Jun 21, 2026
  2. Necmttn commented on Jun 21, 2026

    @Necmttn

    This should be covered by a permission derivation receipt on subagent launch. Record parent rules, subagent rules, effective rules, dropped rules, and actor/session id. If a deny rule is omitted, the test should fail before any tool call happens. Runtime denials should also name the matching rule so users can tell whether the subagent's own policy or the parent policy blocked it.


    Generated with ax.

  3. zaakiy commented on Jul 31, 2026

    @zaakiy

    Try this temporary workaround:

    Using environment variable OPENCODE_DANGEROUSLY_SKIP_PERMISSIONS instead ot flag --dangerously-skip-permissions results in my intended behavior of sub-agents respecting the permission.

    (In my particular scenario, I want to skip permissions, but there may be other environment variables you can use for your scenario).

    OPENCODE_DANGEROUSLY_SKIP_PERMISSIONS=true opencode

    @sesigl @Necmttn @rekram1-node

  4. github-actions commented on Oct 1, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

  5. opencode-agent commented on Oct 1, 2026

    @opencode-agent
    Contributor

    Thanks for raising this. We should have explained the behavior before the issue was closed.

    I checked the latest tagged V1 (v1.18.34) and V2 (v2.0.20). In V1, deriveSubagentSessionPermission builds additional session rules for the child; it does not build its complete effective policy. Tool calls merge the selected subagent’s configured permissions with its session rules, and tool availability uses that merge too. So the subagent's rules are not lost just because the helper doesn't copy them into the session.

    V2 has a different implementation: the child session selects the requested subagent, and permission checks resolve that agent’s own rules. A subagent uses its own permissions, not simply its parent agent’s restrictions; see the current permissions guide. V2 also accepts supported V1 configuration, though its native syntax uses agents.<id>.permissions.

    That explains why the cited helper alone doesn't demonstrate a bypass, but it doesn't rule out a separate reproducible problem. If a direct read tool call still succeeds against a matching deny, please open a new issue with your OpenCode version, a minimal redacted agent config, and the exact tool/action and target path. read and shell/bash are separate permission actions, so please distinguish a direct read from access via a shell command.

    One note on the workaround mentioned above: OPENCODE_DANGEROUSLY_SKIP_PERMISSIONS is not the CLI flag and isn't a supported way to test denies. The --dangerously-skip-permissions flag auto-approves permission prompts; it shouldn't be used to verify that deny rules work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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