Skip to content

permission: broad deny overrides specific allow via findLast() semantics #37935

Closed as not planned

Description

@mgajda

Description

When a broad deny rule (e.g., $HOME/* → deny) appears in the same ruleset as a more specific allow (e.g., $HOME/utilities/* → allow), the evaluate() function uses findLast() which picks the last matching rule — regardless of pattern specificity. The broad deny silently overrides the specific allow, making it impossible to use the pattern "deny everything under a parent path except specific subdirectories."

This affects both V1 (packages/opencode/src/permission/index.ts) and V2 (packages/core/src/permission.ts) permission evaluation, and also means any "always" saved approvals under a broadly denied parent are effectively dead code.

Plugins

None

OpenCode version

dev branch (source)

Steps to reproduce

  1. Configure opencode.jsonc with:
    "external_directory": {
      "$HOME/utilities/*": "allow",
      "$HOME/*": "deny"
    }
    
  2. Try accessing a file under /home/m/Projects/tools/paper-making-system/
  3. Access is denied — the $HOME/* deny wins because it appears later in the ruleset

Screenshot and/or share link

N/A

Operating System

Linux

Terminal

N/A (configuration issue)

Activity

  1. github-actions commented on Jul 20, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    If your issue is distinct (e.g. you've identified a specific new code path or regression), please clarify the differences.

  2. neriousy commented on Oct 22, 2026

    @neriousy
    Member

    This is how V2 is designed to work: the last matching rule wins (see the permissions docs). Put the broad rule first and the exception after it, e.g. "$HOME/": "deny" and then "$HOME/utilities/": "allow". A PR switching to most-specific-wins (#37936) was closed without merging.

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