[PR #5841] feat: glob pattern-based external_directory permission #11609

Open
opened 2026-02-16 18:16:29 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/anomalyco/opencode/pull/5841

State: open
Merged: No


Summary

Fixes #5395 - Extends the external_directory permission with:

  1. Read/write split: Separate read and write permissions for external directory access
  2. Glob pattern-based rules: Fine-grained path-based permission control using glob patterns

Configuration Syntax

Simple permission (backward compatible)

{
  "permission": {
    "external_directory": "allow"
  }
}

Read/write split

{
  "permission": {
    "external_directory": {
      "read": "allow",
      "write": "deny"
    }
  }
}

Glob pattern-based

{
  "permission": {
    "external_directory": {
      "read": {
        "~/reference/**": "allow",
        "~/.ssh/**": "deny",
        "*": "ask"
      },
      "write": {
        "/tmp/**": "allow",
        "*": "deny"
      }
    }
  }
}

Note on pattern evaluation:

  • Patterns are evaluated in insertion order; first match wins
  • * serves as catch-all default (evaluated last)
  • ~ expands to home directory

Tool Behavior

Tool Permission Used
read read
write write
edit write
patch write
bash write

Note on bash tool

Uses write permission conservatively since bash commands can potentially modify files.

Tests

  • Added config schema tests for glob pattern permissions
  • Added tests for split permission in bash.test.ts
  • Created read.test.ts with tests for external directory read permissions

Appendix: Mermaid Flowchart on pattern evaluation

flowchart TD
    A[Receive file path] --> B{Is permission a string?}
    B -->|Yes| C[Return that value]
    B -->|No| D{Is read/write a string?}
    D -->|Yes| E[Return that value]
    D -->|No| F[Iterate through pattern map]
    F --> G{Is current pattern '*'?}
    G -->|Yes| H[Skip and continue to next]
    G -->|No| I{Does pattern match?}
    I -->|Yes| J[Return that value]
    I -->|No| H
    H --> K{More patterns remaining?}
    K -->|Yes| G
    K -->|No| L{Does map have '*' key?}
    L -->|Yes| M["Return map['*']"]
    L -->|No| N[Return undefined = evaluated as allowed]
**Original Pull Request:** https://github.com/anomalyco/opencode/pull/5841 **State:** open **Merged:** No --- ## Summary Fixes #5395 - Extends the `external_directory` permission with: 1. **Read/write split**: Separate `read` and `write` permissions for external directory access 2. **Glob pattern-based rules**: Fine-grained path-based permission control using glob patterns ## Configuration Syntax ### Simple permission (backward compatible) ```json { "permission": { "external_directory": "allow" } } ``` ### Read/write split ```json { "permission": { "external_directory": { "read": "allow", "write": "deny" } } } ``` ### Glob pattern-based ```json { "permission": { "external_directory": { "read": { "~/reference/**": "allow", "~/.ssh/**": "deny", "*": "ask" }, "write": { "/tmp/**": "allow", "*": "deny" } } } } ``` ### Note on pattern evaluation: - Patterns are evaluated in insertion order; first match wins - `*` serves as catch-all default (evaluated last) - `~` expands to home directory ## Tool Behavior | Tool | Permission Used | |-------|-----------------| | read | read | | write | write | | edit | write | | patch | write | | bash | write | ### Note on `bash` tool Uses `write` permission conservatively since bash commands can potentially modify files. ## Tests - Added config schema tests for glob pattern permissions - Added tests for split permission in `bash.test.ts` - Created `read.test.ts` with tests for external directory read permissions ## Appendix: Mermaid Flowchart on pattern evaluation ```mermaid flowchart TD A[Receive file path] --> B{Is permission a string?} B -->|Yes| C[Return that value] B -->|No| D{Is read/write a string?} D -->|Yes| E[Return that value] D -->|No| F[Iterate through pattern map] F --> G{Is current pattern '*'?} G -->|Yes| H[Skip and continue to next] G -->|No| I{Does pattern match?} I -->|Yes| J[Return that value] I -->|No| H H --> K{More patterns remaining?} K -->|Yes| G K -->|No| L{Does map have '*' key?} L -->|Yes| M["Return map['*']"] L -->|No| N[Return undefined = evaluated as allowed] ```
yindo added the pull-request label 2026-02-16 18:16:29 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#11609