Home
Home/s03
s0365 lines of code

Permission Gate

Check Before You Execute

Key Insight:

Dangerous actions need a harness decision point before the shell runs.

Before executing a tool, the harness checks whether the action requires permission. Dangerous commands, such as filesystem writes, network access, and code execution, prompt the user for confirmation. Read-only operations pass through automatically. Because this gate lives at the harness level, every tool receives permission checking without additional code.

Architecture Flow

The Problem: Automation Without Recklessness

An agent with arbitrary tool access is powerful but dangerous. A single hallucinated bash command could delete files, install malware, or exfiltrate data. The solution is not to remove tools but to add a permission gate that classifies every action before execution. Read operations, such as glob, grep, and read, pass through automatically. Write operations, including edit, write, and bash, prompt the user. This approach balances safety with workflow efficiency: the agent moves quickly on safe operations but pauses for confirmation on dangerous ones.

Safety at the Harness Level

The permission gate lives in execute_tool(), not in individual handlers. This is intentional: safety is a cross-cutting concern that should not be duplicated across tools. A single gate protects all tools, including future ones that do not yet exist. The classification function classifyAction() uses both the tool name and the input parameters to determine the danger level. Writing to /etc/passwd is more dangerous than writing to /tmp/test.txt, even though both operations use the write tool.

Design Decisions

The permission check is async, using await promptUser, which means the agent yields control to the user interface. The agent literally waits for human input before proceeding, with no silent approvals.

Danger level classification is not hardcoded. Plugins can register custom classifiers or override default ones through hooks. This allows organizations to enforce their own security policies.

Comparison: Claude Code

Both prioritize permission gates over sandbox isolation. Claude Code requires explicit user approval for file writes and shell commands. OpenCode's permission system takes this further with classifyAction(), a structured classification function that uses wildcard path patterns (allow, deny, ask) rather than simple binary prompts. The Deferred<PermissionEval> pattern means permissions can be pre-evaluated and cached, reducing user prompt fatigue.

Deep Dive: Design Decisions

Gate at the Harness Level, Not the Tool Level

Permissions are checked in the harness, before the tool executes. This means every tool gets permission checking for free — no tool needs to implement its own security logic.

Alternatives: Each tool could implement its own permission checks, but that leads to inconsistent behavior and security gaps. A harness-level gate is the single point of control.

User Must Opt In for Dangerous Actions

Commands that modify the filesystem, access the network, or execute arbitrary code require explicit user confirmation. Read-only operations pass through automatically.

Alternatives: A full auto-approve mode exists for trusted scenarios, but the default is ask-per-action to prevent surprise side effects.

Learn OpenCode — Built with Next.js