Skip to main content
IronClaw runs all untrusted tools in WebAssembly (WASM) sandboxes powered by Wasmtime. This provides strong isolation without the overhead of Docker containers or VMs.

Architecture

Security Guarantees

Memory Isolation

WASM tools run in linear memory completely isolated from the host:
  • Default limit: 10 MB per tool
  • No heap access: Cannot read host memory
  • No pointers: Cannot access arbitrary addresses
  • Bounds checking: All memory accesses validated by WASM runtime
Configured via ResourceLimiter:

CPU Metering

WASM execution is fuel-metered to prevent infinite loops and CPU exhaustion:
  • Fuel: Virtual “gas” consumed per WASM instruction
  • Default limit: Configurable per tool (typically millions of instructions)
  • Epoch interruption: Periodic checks for timeouts
  • Tokio timeout: Hard wall-clock limit (default 30s)
Example from src/tools/wasm/limits.rs:18-28:

No System Access

WASM tools have zero system access by default:
  • ❌ No filesystem (no WASI FS imports)
  • ❌ No raw sockets
  • ❌ No subprocess spawning
  • ❌ No environment variable access
  • ❌ No system clock (host provides now_millis())
All capabilities must be explicitly granted via host functions.

Fresh Instances

Each tool execution creates a fresh WASM instance:
  • Compile once: WASM binary validated and compiled at load time
  • Instantiate per execution: New memory, new store, new state
  • No state reuse: Previous execution’s memory is discarded
  • Side-channel prevention: No shared state between executions
From src/tools/wasm/runtime.rs:

Capability System

All WASM tools start with zero capabilities. Each must be explicitly granted:

Available Capabilities

Capability Configuration

Capabilities are defined in *.capabilities.json files:

HTTP Capability

The most sensitive capability. Enforces:
  1. Host allowlisting: Only approved domains
  2. Path restrictions: Specific API endpoints only
  3. Method controls: GET/POST/etc. per endpoint
  4. Rate limiting: Requests per minute/hour
  5. Size limits: Max request/response body sizes
  6. HTTPS enforcement: No plaintext HTTP
  7. Credential injection: Secrets added by host, not WASM
From src/tools/wasm/capabilities.rs:102-169:

Secrets Capability

Tools can check existence but never read plaintext:
Credentials are injected at the host boundary during HTTP requests. See Credential Management.

Workspace Capability

Read-only access to workspace files with prefix restrictions:
Path validation from src/channels/wasm/capabilities.rs:136-157:

ToolInvoke Capability

Indirect tool access via aliases (prevents direct tool enumeration):
WASM only knows aliases, not real tool names.

Security Constraints

Host Functions (V2 API)

WASM tools interact with the host via these functions:

Logging

Time

Workspace Read

HTTP Request

Secret Exists

Tool Invoke

All string parameters are UTF-8 encoded. Buffers are bounds-checked.

Failure Modes

WASM Trap

If WASM code traps (invalid memory access, division by zero, etc.):
  1. Execution stops immediately
  2. Instance is discarded (never reused)
  3. Error returned to caller
  4. No host state corruption
Example trap handling:

Fuel Exhaustion

Memory Limit Exceeded

Capability Denied

Best Practices

For Tool Authors

  1. Request minimal capabilities: Only what you need
  2. Use tight allowlists: Specific hosts and paths
  3. Handle errors gracefully: Capability denials, rate limits
  4. Avoid secrets in logs: Use secret_exists() checks
  5. Respect fuel limits: Optimize expensive operations

For System Administrators

  1. Audit capabilities.json: Review all granted permissions
  2. Monitor logs: Watch for denied requests (potential attacks)
  3. Rotate secrets: Use expires_at for temporary credentials
  4. Set conservative limits: Start with low fuel/memory, increase if needed
  5. Keep allowlists tight: Only domains you trust

Source Code References

See Also