RustyClaw implements multiple layers of sandbox isolation to protect your system from potentially harmful commands executed by the AI agent. This guide covers sandbox modes, configuration, and security best practices.
Why Sandbox? AI agents execute shell commands on your behalf. While powerful, this poses security risks:
- Accidental deletion of important files
- Exposure of sensitive credentials
- Execution of malicious code
- System-wide damage from bugs
RustyClaw's Defense:
- 🛡️ Multiple sandbox modes (Landlock, Bubblewrap, macOS Sandbox)
- 🚫 Path-based access control
- 🔒 Credential directory protection (automatic)
⚠️ Pre-execution path validation- 🎯 Configurable deny lists
RustyClaw supports 4 sandbox modes, auto-selected based on platform:
What it is: Kernel-level security module (Linux 5.13+) that restricts filesystem access.
How it works:
- Allowlist-based: Only explicitly allowed paths are accessible
- Kernel-enforced restrictions (can't be bypassed)
- Applied per-process (irreversible once set)
- Credentials denied by omission (not in allowlist)
- Automatic fallback if not supported
Allowed by default:
- System paths:
/usr,/lib,/lib64,/bin,/sbin,/etc,/proc,/sys,/dev(read-only) - Temp paths:
/tmp,/var/tmp(read+write) - Workspace directory (full access)
- Any paths in
allow_pathsconfig
Denied by default:
- Everything not in the allowlist
- Home directory (except workspace)
- Credentials directory (
~/.rustyclaw/credentials/) - SSH keys (
~/.ssh/)
Strengths:
- ✅ Strongest security (kernel-level)
- ✅ Fail-closed design (deny by default)
- ✅ No external dependencies
- ✅ Lightweight (no overhead)
Limitations:
- ❌ Linux only (kernel 5.13+)
- ❌ Requires modern kernel
⚠️ Cannot be undone (per-process)
Example denial:
// Agent cannot:
cat ~/.rustyclaw/credentials/secrets.json // ❌ Blocked by Landlock (not in allowlist)
cd ~/.ssh && cat id_rsa // ❌ Blocked by Landlock (not in allowlist)What it is: User namespace sandbox (bwrap) that creates isolated filesystem views.
How it works:
- Creates new mount namespace
- Exposes only approved directories
- Blocks access to everything else
- Each command runs in isolated bubble
Strengths:
- ✅ Very strong isolation
- ✅ Widely available on Linux
- ✅ Per-command sandboxing
- ✅ Flexible configuration
Limitations:
- ❌ Linux only
- ❌ Requires bwrap binary installed
⚠️ Some overhead per command
Installation:
# Ubuntu/Debian
sudo apt-get install bubblewrap
# Fedora/RHEL
sudo dnf install bubblewrap
# Arch
sudo pacman -S bubblewrapExample denial:
# Inside bwrap bubble, only workspace + /tmp visible
ls /home/user/.ssh/ # ❌ Directory doesn't exist
cat /etc/passwd # ❌ File not accessibleWhat it is: Apple's sandbox-exec with Seatbelt profiles.
How it works:
- Uses macOS sandbox-exec command
- Generates Seatbelt policy profiles
- Restricts file operations system-wide
Strengths:
- ✅ Built into macOS (no install needed)
- ✅ Apple-supported
- ✅ Integrates with macOS security
Limitations:
- ❌ macOS only
⚠️ Complex Seatbelt syntax⚠️ Less flexible than Linux options
Example denial:
# Seatbelt profile blocks sensitive paths
sandbox-exec -p "(deny file-read* ...)" commandWhat it is: Pre-execution path checking (no kernel enforcement).
How it works:
- Parses command for file paths
- Checks against deny list
- Rejects command if blocked path detected
Strengths:
- ✅ Works everywhere (portable)
- ✅ No dependencies
- ✅ Fast (no overhead)
Limitations:
- ❌ NOT kernel-enforced (can be bypassed)
- ❌ Only catches obvious path references
⚠️ Parser can be fooled
Use case: Last resort when no other sandbox available.
Edit ~/.rustyclaw/config.toml:
[sandbox]
# Sandbox mode: "auto", "landlock", "bwrap", "macos", "path", "none"
mode = "auto" # Recommended: auto-detect best available
# Additional paths to deny (beyond credentials dir)
deny_paths = [
"/home/user/.ssh",
"/home/user/.gnupg",
"/etc/ssl/private",
"/root",
]
# Paths to explicitly allow in strict mode (optional)
allow_paths = [
"/home/user/projects",
"/tmp",
]Auto (Recommended):
[sandbox]
mode = "auto" # Picks: landlock > bwrap > macos > pathForce Specific Mode:
[sandbox]
mode = "landlock" # Force Landlock (fails if unavailable)Disable (NOT RECOMMENDED):
[sandbox]
mode = "none" # ⚠️ NO PROTECTION - use only for debuggingRustyClaw automatically protects:
~/.rustyclaw/credentials/- Secrets vault- Paths in
sandbox.deny_pathsconfig - SSH keys (if detected)
- GPG keys (if detected)
[sandbox]
mode = "auto"
deny_paths = [
"/home/user/.ssh",
"/home/user/.gnupg",
"/home/user/.aws",
"/home/user/.kube",
"/etc/ssl",
"/etc/ssh",
"/root",
]Result: Agent cannot access credentials, even if compromised.
[sandbox]
mode = "auto"
deny_paths = [
"/home/user/.ssh", # Block SSH keys
# Allow AWS/Kube for development
]Result: Balance between security and functionality.
[sandbox]
mode = "path" # Weakest protection
deny_paths = [] # Nothing denied (except credentials dir)Result: Minimal protection. Use only when troubleshooting.
User Request: "Delete old logs in /var/log"
↓
Gateway receives command
↓
┌─────────────────────────────────┐
│ SANDBOX CHECK │
│ 1. Mode detection │
│ 2. Path validation │
│ 3. Credential check │
└─────────────────────────────────┘
↓
[LANDLOCK MODE]
↓
Apply Landlock restrictions:
- Deny: ~/.rustyclaw/credentials/
- Deny: ~/.ssh/
- Deny: /root/
↓
Execute: rm /var/log/old.log
↓
✅ Success (allowed path)
═══════════════════════════════════
[BLOCKED EXAMPLE]
↓
User: "Show me API keys"
↓
Command: cat ~/.rustyclaw/credentials/secrets.json
↓
Landlock blocks read access
↓
❌ Error: Permission denied
↓
Agent receives error, cannot access secrets
# Agent executes: cat ~/project/file.txt
# RustyClaw wraps with bwrap:
bwrap \
--ro-bind /usr /usr \ # Read-only system files
--ro-bind /lib /lib \ # Read-only libraries
--bind ~/workspace ~/workspace \ # Writable workspace
--bind /tmp /tmp \ # Writable temp
--dev /dev \ # Devices
--proc /proc \ # Process info
--unshare-all \ # Isolate namespaces
--die-with-parent \ # Clean exit
-- \
bash -c "cat ~/project/file.txt"
# Inside bubble:
# - Only sees: /usr, /lib, ~/workspace, /tmp, /dev, /proc
# - Cannot see: ~/.ssh, ~/.gnupg, ~/.rustyclaw/credentialsrustyclaw doctor sandbox
# Output:
# Sandbox Status:
# Mode: Landlock (kernel 5.15.0)
# Protected paths: 3
# - /home/user/.rustyclaw/credentials
# - /home/user/.ssh
# - /home/user/.gnupgMethod 1: Safe test
# Create dummy secret
mkdir -p ~/.rustyclaw/credentials
echo "SECRET=test123" > ~/.rustyclaw/credentials/test.txt
# Try to read (should fail)
rustyclaw command "cat ~/.rustyclaw/credentials/test.txt"
# Expected:
# Error: Permission denied (blocked by Landlock/bwrap)Method 2: Verify deny paths
# Add test deny path
echo '[sandbox]
deny_paths = ["/tmp/blocked"]' >> ~/.rustyclaw/config.toml
# Create test file
mkdir /tmp/blocked
echo "sensitive" > /tmp/blocked/data.txt
# Try to access
rustyclaw command "cat /tmp/blocked/data.txt"
# Expected: Blocked by sandbox# Check what's available on your system
rustyclaw doctor capabilities
# Example output:
# Sandbox Capabilities:
# ✓ Landlock (kernel 5.15.0)
# ✓ Bubblewrap (bwrap 0.5.0)
# ✗ macOS Sandbox (not on macOS)
# Best mode: LandlockSometimes you need to run privileged commands (sudo). RustyClaw supports per-session elevated mode:
In TUI:
/elevated on
In config:
[sandbox]
allow_elevated = true # Allow sudo commands# Elevated mode OFF (default):
sudo rm -rf / # ❌ Blocked by sandbox
# Elevated mode ON:
sudo rm -rf / # ⚠️ ALLOWED (use with caution!)Best practice:
- Keep elevated mode OFF by default
- Enable only when needed
- Disable immediately after use
- Use
/elevated onin TUI (per-session)
Problem:
Agent: "Check SSH config"
Command: cat ~/.ssh/config
Result: ❌ Permission deniedSolution A (Recommended): Use tools that don't need direct access
# Instead of reading file:
Agent: "Show SSH hosts"
Command: ssh -G host | grep hostname
Result: ✅ Works (doesn't need file access)Solution B: Temporarily allow path
[sandbox]
allow_paths = ["/home/user/.ssh/config"] # Read-only accessProblem:
Agent: "Deploy to AWS"
Command: aws s3 cp ... (needs ~/.aws/credentials)
Result: ❌ BlockedSolution: Don't deny AWS paths in development
[sandbox]
deny_paths = [
"/home/user/.ssh",
# "/home/user/.aws", # Commented out for dev work
]Better: Use environment variables instead
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
# Sandbox doesn't block env varsProblem: Sandbox blocks deployment scripts.
Solution: Use mode = "path" for CI
# ci-config.toml
[sandbox]
mode = "path" # Weaker but works in containers
deny_paths = [] # CI already sandboxed by Docker[sandbox]
mode = "auto" # Let RustyClaw pick the strongest available[sandbox]
deny_paths = [
"~/.ssh", # SSH keys
"~/.gnupg", # GPG keys
"~/.aws", # AWS credentials
"~/.kube", # Kubernetes config
"~/.docker", # Docker credentials
"/etc/ssl", # SSL certificates
]# Configure workspace
cd ~/projects/work
rustyclaw chat
# Agent operates in ~/projects/work
# Cannot access parent directoriestotp_enabled = true # Require 2FA for gateway accessDefense in depth: Even if sandbox is bypassed, 2FA protects access.
rustyclaw secrets list
# Remove unused secrets
rustyclaw secrets delete OLD_API_KEY# Enable audit logging
[hooks]
audit_log_hook = true
audit_log_path = "~/.rustyclaw/logs/audit.log"
# Review commands
tail -f ~/.rustyclaw/logs/audit.logProblem:
[sandbox] Landlock not supported (kernel < 5.13)
Solution:
# Check kernel version
uname -r
# If < 5.13: Use bwrap instead
[sandbox]
mode = "bwrap"Or upgrade kernel:
# Ubuntu
sudo apt-get update && sudo apt-get dist-upgradeProblem:
[sandbox] Bubblewrap not available
Solution:
# Install bubblewrap
sudo apt-get install bubblewrap # Ubuntu/Debian
sudo dnf install bubblewrap # Fedora/RHEL
sudo pacman -S bubblewrap # ArchProblem:
Command: cat ~/project/file.txt
Error: Permission deniedDebug:
# 1. Check sandbox mode
rustyclaw doctor sandbox
# 2. Check deny_paths
grep -A 10 '\[sandbox\]' ~/.rustyclaw/config.toml
# 3. Check if parent dir is denied
ls -la ~/ # Is ~/project denied?
# 4. Try with weaker mode
[sandbox]
mode = "path" # Temporarily for debuggingProblem: Sandbox not working?
Verify:
# 1. Check mode
[sandbox]
mode = "auto" # Should auto-detect
# 2. Verify capabilities
rustyclaw doctor capabilities
# 3. Test manually
bwrap --help # Should show help
cat /sys/kernel/security/landlock/abi # Should show number
# 4. Check logs
grep sandbox ~/.rustyclaw/logs/gateway.logIf still not working:
# Force strongest mode
[sandbox]
mode = "landlock" # Will error if not available[sandbox]
mode = "bwrap"
# Fine-grained control
deny_paths = [
"/home/user/.ssh",
"/home/user/secrets",
]
allow_paths = [
"/home/user/projects/public",
"/tmp",
]
# Deny execution of binaries in tmp
deny_exec = ["/tmp"]// In tool implementation
pub fn execute_command(cmd: &str) -> Result<String> {
let policy = SandboxPolicy {
deny_read: vec![
PathBuf::from("/home/user/.ssh"),
PathBuf::from("/etc/passwd"),
],
deny_exec: vec![
PathBuf::from("/tmp"),
],
..Default::default()
};
let mode = SandboxMode::Auto;
let output = run_sandboxed(cmd, &policy, mode)?;
Ok(String::from_utf8_lossy(&output.stdout).to_string())
}| Feature | Landlock | Bubblewrap | macOS Sandbox | Path Validation |
|---|---|---|---|---|
| Platform | Linux 5.13+ | Linux | macOS | All |
| Kernel Enforced | ✅ Yes | ✅ Yes | ✅ Yes | ❌ No |
| Bypass Proof | ✅ Yes | ✅ Yes | ✅ Yes | ❌ No |
| Installation | Built-in | Package | Built-in | Built-in |
| Overhead | None | Low | Low | None |
| Flexibility | High | High | Medium | Low |
| Security | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐ |
| Recommended | ✅ Yes | ✅ Yes | ✅ Yes |
Winner (Linux): Landlock (kernel 5.13+) or Bubblewrap
Winner (macOS): macOS Sandbox
Winner (Windows/Other): Path Validation (
A: Yes, but NOT recommended:
[sandbox]
mode = "none" # ⚠️ NO PROTECTIONBetter: Use weak mode:
[sandbox]
mode = "path" # Some protection, easier debuggingA:
- Landlock: No overhead (kernel-level)
- Bubblewrap: ~50ms per command (namespace creation)
- macOS Sandbox: ~20ms per command
- Path Validation: ~1ms per command
For typical usage: negligible impact.
A:
- Landlock/bwrap/macOS: NO (kernel enforced)
- Path Validation: YES (easily bypassed)
Always use kernel-enforced sandbox in production.
A: Use elevated mode:
/elevated on # In TUI
# Or in config:
[sandbox]
allow_elevated = trueA: No, sandbox is one layer of defense:
What it protects:
- ✅ File access (credentials, SSH keys)
- ✅ Directory traversal
- ✅ Accidental data loss
What it doesn't protect:
- ❌ Network attacks (use firewall)
- ❌ Memory corruption (use safe languages)
- ❌ Logic bugs (use code review)
Defense in depth: Use sandbox + TOTP 2FA + SSRF protection + prompt guards.
- Landlock Documentation
- Bubblewrap GitHub
- macOS Sandbox Guide
- RustyClaw Security Guide
- RustyClaw Configuration
RustyClaw Sandbox Provides:
- ✅ Multiple sandbox modes (auto-selected)
- ✅ Kernel-enforced restrictions (Landlock/bwrap/macOS)
- ✅ Automatic credential protection
- ✅ Configurable deny/allow lists
- ✅ Path validation fallback
- ✅ Testing and verification tools
Recommended Setup:
[sandbox]
mode = "auto" # Auto-detect best mode
deny_paths = [
"~/.ssh",
"~/.gnupg",
"~/.aws",
]
[totp]
enabled = true # Add 2FA for defense in depthStay safe! 🛡️🦞