# How Permission Rules Work for Bash Commands and File Operations in Reasonix

> Understand how Reasonix enforces permission rules for Bash commands and file operations. Learn about its centralized PermissionsView for explicit allow, ask, and deny lists before execution.

- Repository: [YHH/DeepSeek-Reasonix](https://github.com/esengine/DeepSeek-Reasonix)
- Tags: how-to-guide
- Published: 2026-08-08

---

**Reasonix enforces fine-grained permission rules through a centralized `PermissionsView` object that matches every Bash command and file operation against explicit allow, ask, and deny lists before execution.**

The `esengine/DeepSeek-Reasonix` repository implements a deterministic, prompt-aware security model that protects the host environment by intercepting potentially dangerous operations at the bridge layer. Understanding how these permission rules function is essential for developers building plugins or configuring sandboxed environments.

## Permission Architecture Overview

Reasonix employs a **three-tier permission model** that combines frontend state, backend sandbox configuration, and a central bridge layer. Every tool invocation—whether a Bash command or file system operation—must pass through this validation pipeline before reaching the execution kernel.

The system relies on four key components working in concert:

- **`PermissionsView`** – Defines the global mode (`ask`, `allow`, or `deny`) and maintains explicit rule lists for each category.
- **`SandboxView`** – Configures backend-specific restrictions like Bash enforcement status and automatically permitted write directories.
- **Bridge Layer** – Mediates all tool requests in [`desktop/frontend/src/lib/bridge.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/frontend/src/lib/bridge.ts) and applies the rule-matching algorithm.
- **UI Settings** – Provides a Permissions tab for real-time rule management that syncs with the global state.

## Core Components

### PermissionsView (Frontend State)

The permission state lives in [`desktop/frontend/src/lib/types.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/frontend/src/lib/types.ts) and defines the contract for rule-based access control:

```typescript
export interface PermissionsView {
  mode: string;      // "ask" | "allow" | "deny"
  allow: string[];   // explicit allow rules
  ask: string[];     // explicit ask-before-execute rules
  deny: string[];    // explicit deny rules
}

```

Each rule follows the pattern **`<Tool>(<action>:<pattern>)`**. For example, `Bash(rm:*)` targets any `rm` command regardless of arguments, while `ReadFile(/etc/passwd)` matches specific file read operations.

### SandboxView (Backend Configuration)

The backend sandbox configuration, also defined in [`desktop/frontend/src/lib/types.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/frontend/src/lib/types.ts), provides additional hard constraints:

```typescript
export interface SandboxView {
  bash: string;         // "enforce" | "off"
  allowWrite: string[]; // write-allowed directory roots
  // … other sandbox flags
}

```

When `bash` is set to `"enforce"`, every Bash command undergoes permission checking. The `allowWrite` array defines directory roots that are **implicitly writable** without triggering prompts, even when the global mode is set to `ask`.

### Bridge Layer (Rule Matching)

All tool requests funnel through [`desktop/frontend/src/lib/bridge.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/frontend/src/lib/bridge.ts), which constructs **canonical rule strings** and evaluates them against the current permission configuration. The bridge builds rules dynamically from the command context—for instance, parsing `Bash(${command.split(' ')[0]}:${args.join('*')})` to create matchable patterns.

## Rule Matching Algorithm

When a tool is invoked, Reasonix applies a deterministic decision flow with strict precedence:

1. **Rule Construction** – The bridge generates a canonical string (e.g., `Bash(rm:*)` for `rm /tmp/file`).
2. **Ordered Lookup** – The system searches for matches in sequence: first `deny`, then `allow`, then `ask`.
3. **Immediate Action** – If a match is found in any list, the corresponding action executes immediately without checking remaining categories.
4. **Global Fallback** – If no explicit rule matches, the current `mode` value determines the outcome:
   - **`allow`** – Execute the operation silently.
   - **`deny`** – Block the operation and return a `permission denied` error.
   - **`ask`** – Display a confirmation dialog for user approval.

The bridge also validates file writes against `sandbox.allowWrite` roots, rejecting operations outside approved directories unless explicitly permitted by the rule lists.

## Practical Implementation Examples

### Adding Explicit Permission Rules

Configure the permission state programmatically to control specific operations:

```typescript
// settings.permissions is the PermissionsView instance
settings.permissions.allow.push('Bash(ls)');
settings.permissions.deny.push('Bash(rm:*');
settings.permissions.ask.push('ReadFile(/etc/passwd)');
settings.permissions.mode = 'ask'; // Default fallback for unmatched rules

```

This configuration automatically permits `ls` commands, blocks any `rm` invocation, and prompts before reading sensitive system files.

### Handling Bash Commands

Plugin code invoking tools through the bridge automatically respects permission boundaries:

```typescript
import { invokeTool } from '@reasonix/bridge';

// Blocked by the deny rule defined above
await invokeTool('Bash', 'rm /tmp/evil.tmp')
  .catch(err => console.error(err.message)); // → "permission denied"

// Allowed to proceed
await invokeTool('Bash', 'ls -la /home/user');

```

### Restricting File Write Operations

File operations outside the sandbox write roots require explicit permission:

```typescript
import { writeFile } from '@reasonix/fs';

// Fails unless /etc is in sandbox.allowWrite or matched by an allow rule
await writeFile('/etc/hosts', '127.0.0.1 localhost')
  .catch(err => console.error(err.message)); // → "permission denied"

```

The backend Bash execution in [`workers/crash-report/src/shell.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/workers/crash-report/src/shell.ts) only receives commands after the bridge has validated permissions, ensuring no unapproved operations reach the system shell.

## Summary

- **Permission rules** in Reasonix follow the pattern `<Tool>(<action>:<pattern>)` and are evaluated in `deny` → `allow` → `ask` order.
- The **`PermissionsView`** interface in [`desktop/frontend/src/lib/types.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/frontend/src/lib/types.ts) stores explicit rule lists and the global mode setting.
- The **bridge layer** ([`desktop/frontend/src/lib/bridge.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/frontend/src/lib/bridge.ts)) constructs canonical rule strings and mediates every tool request before backend execution.
- **`SandboxView`** provides hard constraints on write directories and Bash availability through the `allowWrite` array and `bash` enforcement flag.
- Unmatched rules fall back to the global mode, with `ask` mode displaying interactive confirmation dialogs to the user.

## Frequently Asked Questions

### What happens if no permission rule matches a Bash command?

If no explicit rule matches the constructed canonical string, the system consults the global `mode` value in `PermissionsView`. When mode is `ask`, the bridge displays a confirmation dialog; when `allow`, it executes silently; when `deny`, it throws a `permission denied` error.

### How do sandbox write roots interact with permission modes?

The `allowWrite` array in `SandboxView` defines directories that are implicitly writable regardless of the global mode. Even under `ask` mode, writes within these roots proceed without prompting, while writes outside require explicit `allow` rules or user confirmation.

### Can plugins bypass the permission system in Reasonix?

No. All tool invocations route through the bridge layer in [`desktop/frontend/src/lib/bridge.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/frontend/src/lib/bridge.ts), which applies rule matching before forwarding requests. The backend shell in [`workers/crash-report/src/shell.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/workers/crash-report/src/shell.ts) only receives already-validated commands, making bypass impossible through standard APIs.

### Where is the permission state stored in the codebase?

The permission state is defined by the `PermissionsView` interface in [`desktop/frontend/src/lib/types.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/frontend/src/lib/types.ts) and persisted in the global settings store (typically managed through [`desktop/frontend/src/lib/settings.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/frontend/src/lib/settings.ts)). The UI synchronizes this state in real-time via the Permissions tab settings panel.