Skip to content

[Feature Request] Unified Built-in Sandbox with Multi-Platform Support and Tiered Presets #12505

@fr33d3m0n

Description

@fr33d3m0n

Type: Feature Request
Category: feature-request
Severity: Critical

Problem Statement

OpenClaw's core architecture includes partial security mechanisms (network binding, Token/password auth, Scope authorization, tool policy allowlists, path sandbox), but these are fragmented, inconsistently applied, and not enforced in the plugin/skill subsystem. All 31+ plugins share a single Node.js process with no process isolation, no memory isolation, and no filesystem isolation. A vulnerability in any single plugin compromises the entire system — including all credentials, data stores, and 250+ SDK APIs. The existing sandbox design (e.g., clawd/sandbox.js path restrictions) has known bypass vulnerabilities (ECO-009). Most critically, there are no user-friendly default presets — requiring users to manually configure security, which most users (especially non-technical ones) never do.

This issue consolidates all sandbox and isolation deficiencies across the ecosystem:

  • Former CSD-001 (No Plugin Sandbox Isolation)
  • Former CSD-002 (Cross-Plugin Credential Exposure via Shared process.env)
  • ECO-004 (Plugin Lateral Movement via Shared Process Model)
  • ECO-005 (Credential Exposure via Shared Environment)
  • ECO-009 (Sandbox Path Traversal — existing sandbox bypass)
  • ECO-014 (Cross-Plugin Credential Leak)
  • ECO-040 (Coding Agent Resource Exhaustion)
  • ECO-045 (Agent Resource Exhaustion Loops)
  • ECO-050 (Unrestricted Tool Execution)

Current State

Architectural Root Cause

OpenClaw loads all 31+ plugins via the jiti (Just-In-Time TypeScript) dynamic loader into a single Node.js process. Every plugin has unrestricted access to:

  • process.env — all 25+ service credentials (Slack, Telegram, OpenAI, Discord, Nostr, blockchain private keys, WeChat AES keys, etc.)
  • Full filesystem — no mount isolation
  • All network connections — no outbound filtering
  • 250+ SDK APIs — no per-plugin capability restrictions
  • All other plugins' memory space — no V8 Isolate boundaries

Existing Partial Sandbox

The clawd/sandbox.js implements basic path restrictions for the sandbox:// URL scheme, but:

  • Path traversal bypass exists (ECO-009, CVSS 9.3)
  • No process-level isolation
  • No credential scoping
  • No network restrictions
  • Not applied to plugins or skills
  • Linux-only — no macOS or Windows equivalent

User Impact

Non-technical users ("beginners") have no way to configure sandbox policies. There are no preset security levels, no guided setup, and no defaults that provide meaningful protection. The result is that security is effectively opt-in and zero users opt in.

Impact Analysis

  • Affected Components: All 31+ extensions, all bundled skills, all community plugins, all ClawHub skills (4,525+)
  • Attack Surface: Any plugin vulnerability becomes system-wide. Cross-plugin lateral movement is trivial (ECO-004). Single credential read grants access to all 25+ integrated services (ECO-005, ECO-014).
  • CVSS Impact: Addresses 9 ECO vulnerabilities with CVSS scores ranging 7.0-9.8, plus the CSD-001/002 architectural defect chain
  • Related Issues: CSD-003, CSD-004, CSD-005, CSD-006, CSD-008, ECO-004, ECO-005, ECO-009, ECO-014, ECO-040, ECO-045, ECO-050

Proposed Solution

Design Principles

  1. Secure by Default: New installations ship with a reasonable sandbox preset enabled — users must opt DOWN, not opt UP
  2. Multi-Platform: Abstract sandbox primitives behind a unified configuration layer; map to platform-native isolation mechanisms
  3. Tiered Presets: 3-4 named security levels that non-technical users can select with a single setting
  4. Progressive Enforcement: Start with the lightest viable isolation, allow upgrading without architecture changes

Multi-Platform Sandbox Architecture

Abstraction Layer

A unified SandboxManager that exposes platform-agnostic capabilities:

Capability Description Configuration Key
Process Isolation Plugin runs in a separate process sandbox.process: true
Filesystem Restriction Read/write limited to declared paths sandbox.fs.allow: [...]
Network Restriction Outbound connections limited to declared hosts sandbox.net.allow: [...]
Credential Scoping Only declared env vars injected sandbox.env.require: [...]
Resource Limits CPU time, memory, file handles capped sandbox.resources: {...}
Syscall Filtering Dangerous system calls blocked sandbox.syscalls: "restricted"

Platform-Native Implementations

Capability Linux macOS Windows Fallback (all platforms)
Process Isolation bubblewrap (bwrap) + namespaces App Sandbox (sandbox-exec) + Seatbelt profiles Win32 AppContainer + Job Objects Node.js child_process.fork() with restricted env
Filesystem Mount namespaces + bind-mounts Sandbox file access rules Restricted Tokens + ACLs chroot-like path validation in proxy
Network Network namespace + iptables/nftables Network extension / PF rules Windows Firewall rules + Job Object net restrictions Proxy-based outbound URL allowlist
Credential Scoping Filtered env in namespace Filtered env in sandbox Filtered env in AppContainer IPC proxy injects only declared vars
Resource Limits cgroups v2 + ulimit launchd resource limits Job Object resource limits Node.js --max-old-space-size + watchdog timer
Syscall Filtering seccomp-bpf Seatbelt syscall profiles Restricted SID + Integrity Level N/A (process boundary only)
Deep Isolation (optional) gVisor (runsc) Virtualization.framework Windows Sandbox / WSL2 isolation Docker container (if available)

IPC Communication Model

Sandboxed plugins communicate with the host via a standardized IPC channel:

  • Transport: Unix domain socket (Linux/macOS) or Named Pipe (Windows), with stdio JSON-RPC as universal fallback
  • Protocol: JSON-RPC 2.0 over the transport
  • SDK Proxy: The host process provides a proxy SDK that marshals API calls across the IPC boundary. Plugins see the same SDK interface; the proxy enforces capability checks before forwarding.

Tiered Preset System

Preset Target User Process Isolation FS Restriction Network Restriction Credential Scope Resource Limits
minimal Developers / self-hosted None (current behavior) Path validation only None Shared process.env None
standard (default) Regular users Separate process per plugin Read-only system dirs; write to plugin data dir Outbound allowlist per plugin manifest Only declared env vars Memory 512MB, CPU 30s per operation
strict Security-conscious users Full platform-native sandbox Minimal filesystem view Strict allowlist + no raw socket Credential vault with on-demand injection Memory 256MB, CPU 10s, 100 file handles
paranoid Enterprise / multi-tenant Deep isolation (gVisor/VM) Ephemeral filesystem per invocation Network namespace + egress proxy HSM-backed credential injection Aggressive limits + watchdog termination

Default: standard — provides meaningful protection without breaking most plugins. Users select their level via:

# ~/.config/openclaw/config.yaml
security:
  sandbox_level: standard  # minimal | standard | strict | paranoid

Plugin Capability Manifest

Each plugin declares its requirements in manifest.yaml:

name: my-plugin
sandbox:
  env:
    require: [OPENAI_API_KEY, MY_PLUGIN_TOKEN]
  fs:
    read: ["./data/**", "/tmp/openclaw/**"]
    write: ["./output/**"]
  net:
    allow: ["api.openai.com:443", "discord.com:443"]
  tools:
    allow: [read, write, message_send]
    deny: [exec, shell]
  commands:
    register: ["/mycommand"]
  http:
    routes: ["/api/myplugin/*"]
    auth: required  # required | optional | none
  resources:
    max_memory: 256MB
    max_cpu_time: 30s

Plugins without a manifest run under the preset's default restrictions. Plugins requesting capabilities beyond the active preset level are either blocked or require explicit user approval.

Implementation Phases

Phase Action Platforms Effort Blocks
Phase 1 IPC proxy SDK layer — abstract plugin-host communication via JSON-RPC; plugins run as child processes with filtered env All High Foundation for all phases
Phase 2 Manifest schema + capability enforcement — parse manifest, enforce at proxy level All Medium Requires Phase 1
Phase 3a Platform-native sandbox (Linux) — bwrap + namespaces + seccomp Linux Medium Requires Phase 1
Phase 3b Platform-native sandbox (macOS) — App Sandbox + Seatbelt macOS Medium Requires Phase 1
Phase 3c Platform-native sandbox (Windows) — AppContainer + Job Objects Windows Medium Requires Phase 1
Phase 4 Tiered preset system + user-facing configuration All Low Requires Phase 2
Phase 5 Optional deep isolation — gVisor (Linux), VM frameworks (macOS/Windows) Per-platform High Optional

Migration Strategy

  1. Ship Phase 1 with minimal as default (backward compatible)
  2. After Phase 2+3, switch default to standard
  3. Existing plugins auto-generate manifest from observed behavior during a "learning" period
  4. Grace period: plugins without manifest run with warnings, then restricted after N releases

Related Issues

Merged into this issue: Former CSD-001 (No Plugin Sandbox), Former CSD-002 (Cross-Plugin Credential Exposure)

Directly addressed ECOs: ECO-004, ECO-005, ECO-009, ECO-014, ECO-040, ECO-045, ECO-050

Architectural dependencies: CSD-003 (code signing works with manifest), CSD-004 (hook integrity benefits from process isolation), CSD-005 (command namespace isolation via manifest), CSD-006 (HTTP auth enforcement via manifest), CSD-008 (instruction isolation via sandbox context separation)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions