# How Reasonix Decomposes Bash Commands for Safe Execution: A Three-Layer Permission System

> Learn how Reasonix safely decomposes Bash commands using a three-layer permission system. Protect your sessions and systems with shell resolution, sandbox wrapping, and data guards.

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

---

**Reasonix protects user sessions and host systems by decomposing every Bash tool call through shell resolution, sandbox-aware command wrapping, and session-data guards before execution.**

The DeepSeek-Reasonix project's permission system treats every Bash command as a potential security boundary. Built in Go, the tool implementation in [`internal/tool/builtin/bash.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/tool/builtin/bash.go) orchestrates multiple defensive layers to prevent session corruption, unauthorized privilege escalation, and resource leakage. This article examines exactly how the source code decomposes and sanitizes Bash commands before they reach the operating system.

## Shell Resolution and Path Hygiene

Before any command executes, Reasonix establishes a clean execution environment that mirrors the user's interactive shell without inheriting risky configurations.

### Lazy Interpreter Resolution

The `resolved()` method in [`bash.go#L26-L36`](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/tool/builtin/bash.go#L26-L36) lazily determines which shell interpreter to invoke—`bash`, `pwsh`, or others—based on the runtime environment and explicit tool parameters. This resolution happens once per tool instantiation and caches the result for subsequent calls.

### Controlled PATH Construction

The `bashCommandEnv` function at [`bash.go#L72-L84`](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/tool/builtin/bash.go#L72-L84) probes the login shell via `defaultBashShellPATH` to extract the user's natural PATH environment. It merges this with the current process PATH while filtering out privileged or unexpected entries. The resulting environment ensures commands execute in a predictable context without ambient privilege leakage from the parent process.

```go
// Simplified illustration of PATH construction logic
func bashCommandEnv() []string {
    loginPath := defaultBashShellPATH()  // Probe interactive shell
    merged := mergeCleanPath(loginPath, os.Getenv("PATH"))
    return []string{"PATH=" + merged}
}

```

## Sandbox-Aware Command Wrapping

Once the environment is prepared, Reasonix evaluates whether the command requires OS-level confinement through its sandbox subsystem.

### The Sandbox Decision Flow

The `bashSandboxCommand` function in [`internal/sandbox/sandbox.go#L41-L56`](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/sandbox/sandbox.go#L41-L56) implements a three-way branching logic:

- **Sandbox disabled**: Execute raw shell command via `argv` directly.
- **Sandbox enforcing + command wrapped**: Proceed with sandbox-encapsulated execution.
- **Sandbox enforcing + command unwrappable**: Trigger user approval workflow.

### Escape Approval for Unsafe Commands

When sandbox enforcement is active but a command cannot be safely wrapped, `approveBashSandboxEscape` at [`bash.go#L48-L60`](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/tool/builtin/bash.go#L48-L60) pauses execution and surfaces a UI prompt. The user must explicitly approve the escape, or Reasonix aborts with a descriptive error. This prevents silent sandbox bypasses for operations like `sudo` invocations or system-level modifications.

```go
// Escape approval workflow example
params := []byte(`{"command":"sudo systemctl restart docker","allow_escape":false}`)
out, err := builtin.Bash{
    sb: sandbox.Spec{Enforce: true},
}.Execute(ctx, params)
// → Returns error: "sandbox escape required but not approved"

```

## Session-Data Guard and Lexical Warning

The final decomposition layer protects Reasonix's own persistent state from accidental corruption by user commands.

### Needle-Based Detection

The `SessionDataGuard` in [`session_guard.go#L27-L33`](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/tool/builtin/session_guard.go#L27-L33) constructs a set of normalized path fragments—"needles"—representing sensitive locations:

- `$REASONIX_ROOT/sessions`
- `projects/*/sessions`
- Runtime ledger files

These needles are lower-cased and slash-normalized to catch case-variant and path-traversal attempts.

### Warning Injection Without Blocking

The `CommandHint` scanner examines both the command string and current working directory. When a needle match occurs, `appendSessionDataHint` at [`bash.go#L31-L41`](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/tool/builtin/bash.go#L31-L41) appends a warning to the command's stdout:

```

WARNING: this command referenced Reasonix's own session/state data under /home/user/.reasonix.
Concurrent modifications may cause conflict-copy loops.

```

Critically, the guard never blocks read operations. It warns specifically about write patterns that could race with Reasonix's autosave mechanisms, preventing infinite conflict-resolution cycles.

```go
// Example: safe command with session-data warning
params := []byte(`{"command":"cat ~/.reasonix/sessions/current/state.json"}`)
out, _ := builtin.Bash{}.Execute(ctx, params)
// → Output: [file contents] + WARNING: this command referenced Reasonix's own session/state data...

// Example: write operation triggers same warning
params := []byte(`{"command":"echo 'corrupt' > ~/.reasonix/sessions/current/state.json"}`)
out, _ := builtin.Bash{}.Execute(ctx, params)
// → Output: (empty) + WARNING: this command referenced Reasonix's own session/state data...

```

## Additional Runtime Safeguards

Beyond the three main layers, Reasonix implements specialized parsers for specific attack patterns:

| Concern | Implementation | Source Location |
|--------|----------------|-----------------|
| **Unquoted command chaining** | `hasUnquotedSeq` rejects `&&` and similar operators in PowerShell contexts to prevent injection | [`bash.go#L62-L68`](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/tool/builtin/bash.go#L62-L68) |
| **Background daemonization** | `hasExplicitBackgroundKeepalive` parses the command AST using `shellparse.ParseBash` to detect `&`, `nohup`, `disown`, and `setsid`, enabling proper process group reaping | [`bash.go#L40-L48`](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/tool/builtin/bash.go#L40-L48) |
| **Foreground timeouts** | `runForeground` applies `bashWaitDelay` via cancellable context; timeouts surface as `command timed out (> 30s)` | [`bash.go#L82-L92`](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/tool/builtin/bash.go#L82-L92) |

The shell parser in [`internal/shellparse/parse.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/shellparse/parse.go) generates a Bash AST, allowing precise detection of backgrounding constructs without false positives from quoted or commented content.

## Code Path Walkthrough

A complete command decomposition traces through these function calls:

1. `Bash.Execute()` — entry point in [[`bash.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/bash.go)](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/tool/builtin/bash.go)
2. `resolved()` — shell interpreter selection
3. `bashCommandEnv()` — PATH sanitization
4. `hasExplicitBackgroundKeepalive()` — AST scan for daemonization
5. `bashSandboxCommand()` — sandbox wrap decision
6. `approveBashSandboxEscape()` — user approval (if needed)
7. `runForeground()` — execution with timeout
8. `appendSessionDataHint()` — session-data warning injection

## Summary

- **Shell resolution** lazily selects interpreters and builds clean PATH environments via `resolved()` and `bashCommandEnv()`.
- **Sandbox wrapping** conditionally applies OS-level confinement through `bashSandboxCommand()`, with mandatory user approval for escapes.
- **Session-data guards** use needle-based lexical scanning to warn about potential state corruption without blocking legitimate reads.
- **Specialized parsers** detect PowerShell injection patterns and background keep-alive constructs before they create resource leaks.
- **Timeout handling** ensures foreground commands cannot hang indefinitely through cancellable contexts.

## Frequently Asked Questions

### How does Reasonix prevent sandbox bypass attacks?

The `approveBashSandboxEscape` mechanism requires explicit user confirmation when sandbox enforcement is active but a command cannot be wrapped. There is no automatic fallback to unwrapped execution—either the user approves the escape through the UI, or the tool returns an abort error. This design eliminates silent bypass vulnerabilities.

### What happens if a command tries to modify Reasonix's session files?

The `SessionDataGuard` detects references to protected paths and appends a warning to the command output. The operation proceeds—Reasonix does not block the write—but the warning alerts users that concurrent modifications may trigger conflict-copy loops with the application's autosave system.

### Why does the background job detector use an AST parser instead of regex?

The `shellparse.ParseBash` function in [`internal/shellparse/parse.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/shellparse/parse.go) generates a proper abstract syntax tree, distinguishing genuine background operators (`cmd &`) from quoted strings, comments, and shell-escaped characters. Regex approaches would produce false positives on constructs like `echo "run &"` or `echo '# nohup'`.