Repository navigation
Description
Feature hasn't been suggested before.
- I have verified this feature I'm about to request hasn't been suggested before.
Describe the enhancement you want to request
OpenCode’s permission engine evaluates bash permissions using a sequential "last-match-wins" evaluation model driven by dictionary merging and rule array iteration.
While simple to implement, this approach creates severe operational friction, maintenance bloat, and safety risks when managing non-trivial CLI permissions across multiple sub-agents:
-
No Grouping or Macro Capabilities: Security policies require explicitly listing every command, sub-command, and flag variation (e.g., repeating dozens of
git,docker,npm, andrtkvariations across every agent file). -
Fragile Rule Ordering: Evaluation relies strictly on document or dictionary insertion order rather than pattern specificity. Accidentally moving a catch-all pattern (
git*or*) below a specific override (such asgit checkout -- *) silently invalidates the finer-grained restriction. -
Ambiguous Inheritance Semantics: Agent inheritance via
extendsperforms a shallow dictionary merge where child rules append after parent rules. Because there is no formal concept of additive delegation versus subtractive boundary enforcement, child agents overwrite parent keys based purely on position. This makes it impossible to predictably build either strict Default-Allow / Subtractive (Boundary) or Default-Deny / Additive (Capability) security topologies.
Security Risk: Host Execution Without Sandboxing
OpenCode agents execute bash commands directly on the host operating system without container isolation or OS-level sandboxing by default.
In an unsandboxed host environment, permission configuration errors carry severe consequences:
-
Unintended data loss (e.g., recursive directory deletion
rm -rf *, uncommitted state discards viagit checkout .*). -
Non-self-contained system alterations (e.g., package manager modifications via
apt,pip install,systemctlmodifications, or privilege escalation viasudo). -
Exfiltration or unexpected network side-effects via
curlorssh.
A permission engine that relies on fragile array ordering and ambiguous inheritance mechanics increases the risk of accidental host compromise.
Real-World Access Control Paradigms
Established access control systems handle permissions using explicit, deterministic evaluation rules rather than document ordering:
-
AWS IAM (Identity and Access Management): Uses Permissions Boundaries (Service Control Policies) for subtractive restriction alongside Identity Policies for additive capabilities. An explicit
Denyin a boundary hard-caps child elevation. -
Kubernetes RBAC: Additive / Least Privilege Model: Operations start denied by default. Roles grant specific capabilities (
verbsonresources). Child/bound roles additively expand access without order-dependent array bugs. -
Linux Security Modules (AppArmor / SELinux): Subtractive Confinement: Profiles strictly limit capabilities. Specific path rules automatically take precedence over broad wildcards regardless of line order in the profile file.
-
Network Firewalls & Policy Engines (Open Policy Agent / Rego): Evaluate ASTs where rule matching prioritizes Pattern Specificity over declaration sequence.
Proposed Solution
Redesign OpenCode's permission engine around a deterministic, multi-tiered resolution model that supports both additive and subtractive configuration styles.
1. Command Grouping (Macros / Aliases)
Allow defining reusable command arrays in the root opencode.json so agents can reference whole categories of actions rather than maintaining exhaustive flag lists.
2. Pattern Specificity Engine (Glob Trie / AST)
Eliminate line-order sensitivity. When a command is executed, match all applicable globs and resolve conflicts using pattern specificity. Exact subcommands (git branch --delete*) take precedence over broader subcommands (git branch*), which take precedence over global wildcards (git* or *).
3. Clear Rule Resolution Hierarchy
Resolve overlapping permission decisions using a deterministic 3-step evaluation order:
- Specificity First: The rule matching the most specific glob pattern always wins (e.g.,
rm -rf /beats@destructive-git-safeor*). - Locality / Inheritance Scope: When glob patterns are identical in specificity, the most local rule wins (e.g., a child agent's rule for
rm *overrides an inherited parent or global rule forrm *). - Configurable Verb Precedence (Fallback): When rules conflict at the exact same specificity and scope level, apply the policy's resolution strategy (e.g.,
Deny>Ask>Allowinstrictmode, orAllow>Ask>Denyinpermissivemode).
4. Explicit Inheritance Modes (mode: additive vs mode: subtractive)
To remove ambiguity, formalize permission inheritance in child agents using an explicit mode directive:
-
mode: additive(Capability Grants / Default-Deny):- The parent establishes the baseline bounds.
- The child uses
mode: additiveto widen access (e.g., elevating@destructive-git-safefromask$\rightarrow$ allow).
-
mode: subtractive(Guardrails / Default-Allow):- The parent provides broad access.
- The child uses
mode: subtractiveto narrow access (e.g., downgrading@destructivefromallow$\rightarrow$ deny).
-
Enforceable Boundaries (
sealedrules):- Rules declared in
opencode.jsonor parent agents usingsealed: true(or aseal:block) create a permission ceiling/floor that child agents cannot override, regardless of inheritance mode or local specificity.
- Rules declared in
Proposed Configuration Examples
Root Configuration (opencode.jsonc)
Define macro groups, baseline defaults, and un-overrideable hard boundaries:
{
"$schema": "https://opencode.ai/config.json",
"permission": {
// Reusable command groups
"groups": {
"@read-only": [
"rtk git status*", "rtk git log*", "rtk git diff*", "rtk ls*", "rtk rg*", "pwd"
],
"@mutation": [
"bun build*", "bun install*", "rtk cargo build*", "mkdir *", "touch *"
],
"@destructive-git-safe": [
"cp *", "rtk git add*", "git rm*", "mv *", "rm *"
],
"@destructive": [
"apt *", "sudo *", "rtk git checkout -- *", "git clean*", "rm -rf *"
]
},
"bash": {
"default": "deny",
// Universal baseline permissions
"rules": {
"@read-only": "allow",
"@mutation": "deny",
"@destructive-git-safe": "deny",
"@destructive": "deny"
},
// Sealed boundaries that no agent or sub-agent can override
"seal": {
"sudo *": "deny",
"rm -rf /": "deny"
}
}
}
}
Additive Inheritance Example: Building Capabilities Top-Down
In an additive setup, the base agent starts restricted, and child agents selectively elevate capabilities.
Base Agent (.opencode/agents/adhoc.yaml)
name: adhoc
description: Ad-hoc runner with intermediate interactive capabilities
mode: subagent
permission:
bash:
mode: additive # Explicitly state that rules in this block elevate privileges
rules:
"@mutation": allow
"@destructive-git-safe": ask
"@destructive": ask
Child Agent (.opencode/agents/coder.yaml)
coder extends adhoc. Because it specifies mode: additive, it additively expands git-safe operations from ask to allow, while specific pattern overrides (git push --force*) protect critical workflows regardless of declaration order.
name: coder
description: Primary development agent
mode: subagent
extends: adhoc
permission:
bash:
mode: additive # Widens permissions inherited from 'adhoc'
rules:
# Capability Elevation: Elevates '@destructive-git-safe' from 'ask' -> 'allow'
"@destructive-git-safe": allow
# Specific glob override (Specificity Engine ensures this beats '@destructive-git-safe')
"git push --force*": ask
Subtractive Inheritance Example: Applying Guardrails Bottom-Up
In a subtractive setup, a parent agent starts with broad permissions, and specialized sub-agents narrow the blast radius.
Base Autonomous Agent (.opencode/agents/power-user.yaml)
name: power-user
description: High-privilege agent for automated environment setup
mode: subagent
permission:
bash:
mode: additive
rules:
"@mutation": allow
"@destructive-git-safe": allow
"@destructive": allow
Specialized Restricted Child (.opencode/agents/reviewer.yaml)
reviewer inherits broad power from power-user, but uses mode: subtractive to enforce narrow security guardrails for safe code review.
name: reviewer
description: Code review sub-agent constrained to safe operations
mode: subagent
extends: power-user
permission:
bash:
mode: subtractive # Narrows/restricts permissions inherited from 'power-user'
rules:
# Restricts mutations to interactive prompts
"@mutation": ask
# Hard-denies destructive actions regardless of parent 'allow'
"@destructive-git-safe": deny
"@destructive": deny
Expected Impact
- Determinism: Eliminates hidden bugs caused by TOML key sorting or JSON rule array placement.
- Flexibility: Cleanly supports both Default-Deny additive capability workflows and Default-Allow subtractive boundary workflows via explicit
modedeclarations. - Maintainability: Reduces agent frontmatter definitions by 80–90% through reusable command groups.
- Host Safety: Guarantees that explicit system safety rules (e.g.,
sudo *,rm -rf /) sealed at the global layer cannot be accidentally bypassed by sub-agent extensions.
Activity
github-actions commentedon Aug 6, 2026
This issue might be a duplicate of or closely related to existing issues. Please check:
Your proposal goes further than any single one of these (adding macros, a specificity engine, and explicit inheritance modes), but the core problems it addresses are already tracked across those issues. It may be worth referencing or commenting on those threads to consolidate discussion.
rmanish2000-del commentedon Aug 21, 2026
"Order-dependent (first-match) permission evaluation" versus specificity and precedence - I hit the same wall and went the other way: precedence is fixed as clause order, and it's written into a spec with a conformance corpus so a second implementation can be checked against it.
I don't think that's obviously right, which is why I'm writing.
Two routes are still open: globs expand after the decision, and a global flag taking a separate value displaces the subcommand - git -c core.pager=cat push --force slips a rule denying git push --force.
https://github.com/rmanish2000-del/warrant-mcp/blob/main/writing/bypass-hunt.md
Did set-based inheritance come from a real rule collision, or from reading the evaluation code?
Early, one person, nobody using it.
rmanish2000-del commentedon Aug 21, 2026
"Order-dependent (first-match) permission evaluation" versus specificity and precedence - I hit the same wall and went the other way: precedence is fixed as clause order, and it's written into a spec with a conformance corpus so a second implementation can be checked against it.
I don't think that's obviously right, which is why I'm writing.
Two routes are still open: globs expand after the decision, and a global flag taking a separate value displaces the subcommand - git -c core.pager=cat push --force slips a rule denying git push --force.
https://github.com/rmanish2000-del/warrant-mcp/blob/main/writing/bypass-hunt.md
Did set-based inheritance come from a real rule collision, or from reading the evaluation code?
Early, one person, nobody using it.
chances190 commentedon Aug 28, 2026
Thanks for sharing the
warrant-mcpwriteup.You make a solid point regarding pattern specificity. Trying to compute "specificity" dynamically on raw command strings without full AST canonicalization introduces edge cases (like flag displacement) where human intent becomes ambiguous. Given that building a parser flexible enough for every CLI tool isn't practical at this layer, sticking to a explicit, predictable top-to-bottom (first-match-wins) evaluation model is definitely the cleaner mental model.
The core problem I hit in practice was about inheritance when orchestrating permissions across agent hierarchies.
Right now, sub-agent inheritance relies on shallow dictionary merging, which makes child rules append/overwrite based strictly on key placement. To manage permissions across a team of sub-agents without accidental bypasses or bloat, three things would solve the bulk of the friction:
@read-onlyor@destructivecommand lists centrally so sub-agents don't have to duplicate flag strings across multiple files.Whether the matching under the hood relies on ordered globs or an actual syntax parser (like tree-sitter-bash), having a deterministic inheritance framework prevents developers from fighting merge order between agents.
github-actions commentedon Oct 28, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.