Skip to main content

Sandboxing

WASP executes code and commands as part of its skill system. This page describes the sandboxing mechanisms in place and their limitations.

Container Isolation

All WASP services run in Docker containers with non-root users (UID 1000), except agent-broker which runs as root (required for Docker socket access).

The agent container itself:

  • Non-root user
  • No --privileged flag
  • Docker socket mounted as :ro (read-only) — prevents direct container manipulation
  • All destructive Docker commands go through agent-broker allowlist

Shell Skill Sandboxing

The shell skill executes commands via asyncio.create_subprocess_exec():

process = await asyncio.create_subprocess_exec(
*shlex.split(command),
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
cwd="/data", # Default working directory
)

Constraints:

  • Default timeout: 60 seconds
  • Maximum timeout: 120 seconds
  • Output capped at 8,000 characters
  • Working directory: /data (inside container)

What this means: The shell skill has full access to the agent container's filesystem and can run any command the agent user can run. The container itself is the sandbox.

Python Exec Sandboxing

The python_exec skill writes code to a temp file and executes it as a subprocess:

with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
f.write(code)
tmpfile = f.name

process = await asyncio.create_subprocess_exec(
sys.executable, tmpfile,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
)

Constraints:

  • Default timeout: 60 seconds
  • Maximum timeout: 120 seconds
  • Output capped at 8,000 characters
  • No additional sandbox (runs as same user)

Skill Evolution Sandboxing

Generated skills are validated via AST before execution:

_DANGEROUS_IMPORTS = {
"subprocess", "os", "sys", "pty", "ctypes", "pickle",
"marshal", "importlib", "__import__", "eval", "exec", "compile",
}

The AST scanner checks all import statements and function calls. Code that imports or calls dangerous functions is rejected before execution.

Note: This is defense-in-depth, not a complete sandbox. A sophisticated prompt injection could potentially generate valid Python that bypasses import restrictions through indirect means.

HTTP Request SSRF Protection

The http_request skill blocks requests to private/metadata endpoints:

_SSRF_BLOCKED = [
# RFC-1918 private ranges
r"^10\.",
r"^172\.(1[6-9]|2[0-9]|3[01])\.",
r"^192\.168\.",
r"^127\.",
# Cloud metadata
r"169\.254\.169\.254", # AWS metadata
r"metadata\.google\.internal",
]

Before executing any HTTP request, the target hostname is resolved and checked against these patterns.

File System Access

The read_file and write_file skills have unrestricted access within the container. The self_improve skill uses os.path.realpath() for containment checks:

real_path = os.path.realpath(requested_path)
if not real_path.startswith("/app/src/"):
raise PermissionError("Path traversal attempt blocked")

Anticipatory Simulation

For RESTRICTED and PRIVILEGED skills, the agent runs a pre-execution simulation. This is not a security control — it's a cognitive self-check that allows the LLM to reconsider an action before execution.

Browser Isolation

The browser skill runs Chromium in headless mode:

  • No GPU acceleration (headless)
  • Profile directories isolated per session name
  • Screenshots saved to /data/screenshots/
  • Sessions can be named to maintain state across calls

Secrets in Memory

Credentials are stored in Redis with encryption (via SecretVault). The vault key is derived from DASHBOARD_SECRET.

Never stored in plaintext:

  • Integration API keys
  • Gmail credentials

Always redacted in audit logs (see Secret Redaction).

Security Best Practices

  1. Keep TELEGRAM_ALLOWED_USERS restricted — only your Telegram user IDs
  2. Use a strong DASHBOARD_SECRET — minimum 16 chars, use a random string
  3. Don't expose port 8080 directly — use the nginx proxy
  4. Regularly review audit logs — check for unexpected skill calls
  5. Consider SKILL_EVOLUTION_ENABLED=false for maximum code safety
  6. Run on a dedicated server — don't share with other services