Skip to main content
Sandbox backends provide isolated command execution environments with explicit shell control to prevent injection attacks while enabling shell features when needed.

Quick Start

1

Safe Command Execution

Execute commands safely without shell features:
from praisonaiagents import Agent
from praisonai.sandbox import SubprocessSandbox

# Create agent with safe command execution
agent = Agent(
    name="System Agent",
    instructions="Execute system commands safely",
)

# Create sandbox for safe execution
sandbox = SubprocessSandbox()

# Execute without shell (default, safe)
result = await sandbox.run_command("ls -la")
print(result.stdout)
2

With Shell Features

Enable shell features when needed:
from praisonaiagents import Agent
from praisonai.sandbox import DockerSandbox

agent = Agent(
    name="Data Agent", 
    instructions="Process data with shell pipelines"
)

sandbox = DockerSandbox()

# Execute with shell features (explicit opt-in)
result = await sandbox.run_command(
    "cat data.txt | grep 'error' | wc -l",
    shell=True
)
print(f"Error count: {result.stdout.strip()}")

How It Works

BackendUse CaseSecurity Level
SubprocessSandboxLocal development, scriptsMedium (OS-level isolation)
DockerSandboxProduction, untrusted codeHigh (container isolation)
SSHSandboxRemote executionHigh (network isolation)

Configuration Options

Shell Parameter Control

# String commands are parsed safely
result = await sandbox.run_command("python script.py --arg value")

# List commands are executed directly
result = await sandbox.run_command(["python", "script.py", "--arg", "value"])
Security: No shell injection possible. String commands are parsed with shlex.split().
Set shell=True only when you need shell features (pipes, &&, globbing). With untrusted input always keep shell=False.

Decision Guide

Use CaseRecommended shell Value
Running a single executable with argumentsFalse
Pipelines (grep | sort)True
Globs and env-var expansionTrue
Untrusted / model-generated commandsFalse

Common Patterns

Backend Selection

from praisonai.sandbox import SubprocessSandbox

# Local development with subprocess
sandbox = SubprocessSandbox()
result = await sandbox.run_command("python test.py")

Safe Data Processing

from praisonai.sandbox import DockerSandbox

sandbox = DockerSandbox()

# Process user data safely
async def process_file(filename):
    # Safe: no shell injection possible
    result = await sandbox.run_command([
        "python", "process.py", "--input", filename
    ], shell=False)
    return result.stdout

# Process with shell features when controlled
async def count_errors(log_file):
    import shlex
    # Trusted input, need shell features  
    result = await sandbox.run_command(
        f"grep 'ERROR' {shlex.quote(log_file)} | wc -l",
        shell=True
    )
    return int(result.stdout.strip())

Resource Limits

from praisonai.sandbox import ResourceLimits, SubprocessSandbox

limits = ResourceLimits(
    timeout_seconds=30,
    memory_mb=512
)

sandbox = SubprocessSandbox()
result = await sandbox.run_command(
    "python heavy_task.py",
    limits=limits,
    shell=False
)

Best Practices

Model-generated commands or user input should never use shell=True to prevent injection attacks. The default shell=False provides automatic protection.
# ✅ Safe with any user input
user_script = request.get("script")
result = await sandbox.run_command(f"python {user_script}", shell=False)

# ❌ Vulnerable to injection
result = await sandbox.run_command(f"python {user_script}", shell=True)
If you must use shell=True, quote all dynamic arguments with shlex.quote():
import shlex

filename = user_input  # Could contain special characters
command = f"process.py --file {shlex.quote(filename)}"
result = await sandbox.run_command(command, shell=True)
Using argument lists avoids shell parsing entirely:
# ✅ Clear and injection-safe
result = await sandbox.run_command([
    "python", "script.py", 
    "--input", input_file,
    "--output", output_file
], shell=False)

# ❌ Requires careful quoting
import shlex
command = f"python script.py --input {shlex.quote(input_file)} --output {shlex.quote(output_file)}"
result = await sandbox.run_command(command, shell=True)
Choose the sandbox backend based on your isolation requirements:
  • Development: SubprocessSandbox for speed and convenience
  • Production: DockerSandbox for container-level isolation
  • Remote: SSHSandbox for network-isolated execution
  • High Security: Always use Docker or SSH backends with shell=False

Resource Limits

Configure timeouts and memory limits for sandbox execution

Thread Safety

Understanding thread-safe operations across PraisonAI components