How to Set Up Sandbox and Workspace_Root Constraints for File Operations in Reasonix
TLDR: Reasonix isolates file-write operations using a sandbox configured in reasonix.toml where workspace_root defines the base directory and allow_write lists additional permitted paths, enforced via OS-level jails on macOS when mode = "enforce".
The esengine/DeepSeek-Reasonix repository implements a security model that constrains AI-driven file operations to designated directories. By configuring sandbox and workspace_root constraints for file operations in Reasonix, you prevent unauthorized writes outside your project boundaries while maintaining flexibility for temporary or data directories. This system ensures that tools like write_file, edit_file, and move_file cannot escape the intended directory hierarchy.
Understanding the Sandbox Architecture
Reasonix employs a sandbox that acts as a jail for the built-in Bash tool, which executes all file-writing commands. The configuration resides in a reasonix.toml file and controls two primary security boundaries.
Core Configuration Parameters
The sandbox recognizes two critical settings that define the write perimeter:
workspace_root: The absolute base directory that any file-writer may touch. When set to an empty string (""), it defaults to the current working directory at runtime. Paths outside this directory are rejected.allow_write: A list of additional absolute paths permitted for writes (e.g.,/tmp, user data directories). By default, this list is empty.
Enforcement Modes
The mode setting determines whether the sandbox is active:
enforce: Activates OS-level sandboxing using macOS Seatbelt. On other operating systems, this runs unconfined.off: Disables sandbox restrictions entirely.
The default is "enforce" for macOS and "off" for Linux and Windows.
Configuring the Sandbox in reasonix.toml
To activate constraints, create or modify reasonix.toml in your project root:
[sandbox]
mode = "enforce"
workspace_root = "/absolute/path/to/project"
allow_write = ["/tmp", "/home/user/data"]
Save the file and restart Reasonix. The configuration reloads automatically, applying the new constraints to subsequent file operations.
Implementation Deep Dive
The constraint system spans multiple packages in the esengine/DeepSeek-Reasonix codebase, from configuration rendering to runtime enforcement.
Configuration Rendering in render.go
The internal/config/render.go file handles emitting the sandbox section into the generated TOML. Lines 388–394 contain the explanatory comment describing write restrictions, while lines 392–394 handle the emission of the workspace_root value when present. This ensures the sandbox.Spec struct is correctly populated from the configuration file.
Runtime Enforcement in confine.go and sandbox.go
The actual enforcement logic resides in internal/tool/builtin/confine.go. At line 85–87, the code constructs a sandbox.Spec containing the WorkspaceRoot and AllowWrite entries, then passes this specification to the Bash tool wrapper. The comment explicitly states that writes are only allowed inside the workspace root or any allow_write entries.
The core implementation lives in internal/sandbox/sandbox.go:
- Lines 1–28: Define the
Specstruct containingWorkspaceRootandAllowWritefields, along with the package description. - Lines 11–20: Implement the
Commandfunction that builds thesandbox-execcommand on macOS, returning the argv array that runs the command inside the OS sandbox.
When sandbox.Available() returns false (on non-macOS systems), commands run unconfined. The doctor/report.go file (lines 80–84) marks the sandbox as inactive in these cases.
Desktop Workspace Persistence
For desktop UI users, desktop/workspace.go manages the last accessed folder under the user's Reasonix config directory (desktop-workspace). Lines 21–27 and 38–46 handle reading and writing this state. While this provides a default workspace_root, the sandbox constraints still apply to any file-writer invoked from the UI.
Runtime Behavior and Constraints
Understanding how the sandbox behaves at runtime prevents unexpected failures during file operations.
- Write Restrictions: Any write attempt resolving outside
workspace_rootand not listed inallow_writecauses the sandbox to abort and return an error (e.g.,write outside root should be denied by the sandbox). This behavior is verified inconfine_test.goat line 162. - Read Permissions: The sandbox only restricts write operations; read operations remain unrestricted regardless of path.
- Path Resolution: Relative paths like
../outside.txtare resolved againstworkspace_rootand rejected if the absolute result falls outside the allowed boundary.
Practical Implementation Example
Below is a minimal Go example demonstrating how Reasonix invokes a file-write tool that respects the sandbox constraints:
// Configure the sandbox specification
spec := sandbox.Spec{
Mode: "enforce",
WorkspaceRoot: "/home/alice/projects/myapp",
AllowWrite: []string{"/tmp"},
}
// Initialize the Bash tool with sandbox confinement
bashTool := tool.Builtin("bash", sandbox.Spec{
Mode: "enforce",
WorkspaceRoot: spec.WorkspaceRoot,
})
// Execute a write operation - this will succeed
result, err := bashTool.Run(ctx, "write_file", map[string]any{
"path": "src/main.go", // Resolves to /home/alice/projects/myapp/src/main.go
"content": "package main\nfunc main() {}",
})
// This would fail - resolves outside workspace_root
// result, err := bashTool.Run(ctx, "write_file", map[string]any{
// "path": "../outside.txt",
// })
Summary
- Sandbox Configuration: Define
workspace_rootandallow_writeinreasonix.tomlto restrict file operations to specific directories. - OS Enforcement: macOS uses Seatbelt for OS-level jailing when
mode = "enforce"; other platforms run unconfined. - Source Locations: Configuration renders via
internal/config/render.go, enforcement logic lives ininternal/tool/builtin/confine.goandinternal/sandbox/sandbox.go, and desktop state persists indesktop/workspace.go. - Security Model: Writes are strictly confined to
workspace_rootplus explicitallow_writepaths, while reads remain unrestricted.
Frequently Asked Questions
What happens if I don't set workspace_root?
If workspace_root is omitted or set to an empty string in reasonix.toml, Reasonix defaults to the current working directory at runtime. However, this is less secure than explicit configuration, as the effective root depends on where the process starts.
How does the sandbox behave on Linux or Windows?
On Linux and Windows, sandbox.Available() returns false, causing the Bash tool to run unconfined regardless of the mode setting. The doctor/report.go module will indicate the sandbox is inactive. Reasonix currently only implements OS-level jailing via macOS Seatbelt.
Can I allow writes outside the workspace_root?
Yes, by adding absolute paths to the allow_write array in reasonix.toml. For example, allow_write = ["/tmp", "/var/log/myapp"] permits writes to those specific directories even if they fall outside workspace_root. All other external paths remain blocked when mode = "enforce".
Where does Reasonix store the desktop workspace state?
The desktop application persists the last used folder in the user's Reasonix configuration directory under the desktop-workspace key. The desktop/workspace.go file handles this storage at lines 21–27 and 38–46, retrieving the stored path to use as the default workspace_root in subsequent sessions.
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 →