Permission System for Bash Command Approval and Sandboxing in Reasonix
Reasonix enforces a layered permission hierarchy that evaluates Bash commands through a deny → ask → allow → fallback sequence, combining regex-based access control lists with OS-level sandboxing via Seatbelt or bubblewrap to isolate shell execution from the host filesystem.
The permission system for bash command approval and sandboxing in Reasonix provides fine-grained governance over shell commands executed by the AI agent. According to the esengine/DeepSeek-Reasonix source code, the platform implements a fail-closed security model where write-capable tools default to explicit user approval unless explicitly configured otherwise. This architecture ensures that potentially destructive operations require human verification while maintaining developer productivity through configurable automation.
Permission Hierarchy and Evaluation Order
Every tool invocation in Reasonix traverses a strict evaluation sequence defined in site/src/pages/docs.astro. The system processes permissions in the following order: deny → ask → allow → fallback.
Read-only tools typically pass automatically, but write-capable tools—including Bash—respect the configured [permissions] mode. The default posture is ask, which triggers an interactive prompt before executing any Bash command that modifies the system.
When evaluating a command, Reasonix checks explicit deny lists first, followed by allow lists. If neither list matches, the system falls back to the global mode setting. This hierarchy ensures that dangerous patterns like rm -rf are blocked immediately, regardless of broader permission settings.
Explicit Deny and Allow Lists
The opencode.json file at the repository root defines global permission defaults and per-tool regex patterns. Administrators can specify wildcard denials ("*": "deny") alongside granular Bash-specific rules.
The configuration uses regex patterns to match command strings. For example, the following rules demonstrate typical security boundaries:
# ~/.reasonix/config.toml
[permissions]
mode = "ask"
deny = ["Bash(rm -rf*)", "Bash(git push*)"]
allow = ["Bash(go test:*)"]
Entries like Bash(rm -rf*) prevent recursive deletion operations, while Bash(go test:*) permits testing workflows without manual approval. These patterns are evaluated against the raw command string before execution, providing deterministic control over shell access.
Dynamic Bash Opt-In for Indirect Execution
By default, Bash commands executed indirectly—such as those spawned by other tools—follow the standard permission flow. Setting allow_dynamic_bash = true in the [permissions] section modifies this behavior to permit indirect Bash execution when the global mode is set to allow.
As documented in site/src/pages/docs.astro, this opt-in prevents accidental shell escapes through tool chains while enabling sophisticated automation workflows. Without this flag, even indirect Bash invocations respect the deny/ask/allow hierarchy, ensuring that write operations cannot bypass user consent through intermediary tools.
Sandboxing Architecture and Filesystem Restrictions
Workspace Isolation and Path Resolution
All file-writing tools, including Bash when spawning subshells, must operate within the configured [sandbox] workspace_root. By default, this resolves to the current working directory. The sandbox implementation resolves symlinks and normalizes .. path segments to prevent directory traversal attacks.
The configuration supports explicit read and write restrictions:
[sandbox]
workspace_root = "" # Empty string defaults to current directory
allow_write = ["/tmp"] # Writable paths inside the sandbox
forbid_read = ["${HOME}/.ssh"] # Paths blocked from read access
OS-Level Sandbox Enforcement
Reasonix supports mandatory OS-level isolation through the bash configuration option, which accepts "enforce" or "off". When set to "enforce" and a compatible backend is present—Seatbelt on macOS or bubblewrap on Linux—Bash commands execute within a restricted environment isolated from the host filesystem.
If enforcement is enabled but no sandbox backend is available, Reasonix rejects the Bash command rather than executing it unconfined. This fail-closed behavior, described in site/src/pages/docs.astro, prevents accidental exposure of sensitive system resources when security dependencies are missing.
Headless Execution Safety Controls
The reasonix run command defaults to the Ask posture for all write-capable operations. In headless or CI environments, Bash commands will fail closed unless explicitly authorized via command-line flags.
To enable automated execution, supply one of the following options:
# Auto-approve safe commands in headless mode
reasonix run -y "go test ./..."
# Or use the explicit permission mode flag
reasonix run --permission-mode auto "build_script.sh"
Without these flags, any Bash invocation requiring write access terminates with a permission error rather than hanging indefinitely for user input. This design ensures that unattended runs cannot invoke destructive shell commands without explicit configuration.
Summary
- Hierarchical evaluation: Reasonix processes permissions as deny → ask → allow → fallback, with Bash defaulting to the
askmode unless explicitly configured. - Regex-based ACLs: The
opencode.jsonandconfig.tomlfiles support pattern-based deny and allow lists for precise command filtering. - Indirect execution control: The
allow_dynamic_bashsetting governs whether indirect Bash calls (from other tools) respect theallowmode or require explicit approval. - Filesystem sandboxing: The
workspace_rootparameter confines all write operations, with symlink resolution and path normalization preventing directory escape. - OS-level isolation: Setting
bash = "enforce"requires Seatbelt (macOS) or bubblewrap (Linux); commands fail rather than run unconfined if backends are unavailable. - Headless safety:
reasonix rundefaults to interactive approval; automated workflows require-y,--auto, or--permission-mode autoto proceed.
Frequently Asked Questions
How does Reasonix determine whether to prompt for Bash command approval?
Reasonix evaluates every Bash command against the permission hierarchy defined in site/src/pages/docs.astro. First, it checks explicit deny lists (blocking matches immediately), then allow lists (auto-approving matches). If no pattern matches, it falls back to the global mode setting—defaulting to ask, which triggers an interactive prompt before execution.
What configuration files control Bash permissions and sandboxing?
Permissions are defined in opencode.json at the repository level for global defaults, and in ~/.reasonix/config.toml or project-local reasonix.toml for runtime settings. The [permissions] section controls approval modes and regex patterns, while the [sandbox] section defines workspace_root and path restrictions. OS-level enforcement is toggled via the [tools] bash setting.
Can Reasonix block Bash commands executed indirectly by other tools?
Yes. Without allow_dynamic_bash = true in the [permissions] section, Bash commands spawned indirectly (e.g., by another tool invoking a shell) still traverse the deny/ask/allow hierarchy. Enabling this setting allows the allow mode to cover indirect execution, while deny rules remain enforced regardless of this flag.
What happens if the OS-level sandbox backend is unavailable?
When bash = "enforce" is configured but Reasonix cannot detect Seatbelt (macOS) or bubblewrap (Linux), the system rejects the Bash command entirely rather than executing it without sandboxing. This fail-closed behavior ensures that security policies are never silently degraded due to missing dependencies.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →