mirror of
https://github.com/nearai/ironclaw.git
synced 2026-09-03 08:06:01 +08:00
202 lines
6.0 KiB
Plaintext
202 lines
6.0 KiB
Plaintext
---
|
|
title: WASM Tools
|
|
sidebarTitle: Sandboxed Tools
|
|
description: Sandboxed tool execution via WebAssembly (wasmtime)
|
|
---
|
|
|
|
WASM tools run inside a WebAssembly sandbox powered by [wasmtime](https://wasmtime.dev/). They have access to IronClaw's host functions (logging, time, workspace), but all other capabilities — network, filesystem, credentials — must be explicitly declared in a `capabilities.json` file.
|
|
|
|
This is IronClaw's recommended approach for custom integrations that need stronger isolation than a built-in Rust tool provides.
|
|
|
|
---
|
|
|
|
## How It Works
|
|
|
|
```
|
|
LLM selects tool
|
|
↓
|
|
IronClaw loads WASM module (from cache or disk)
|
|
↓
|
|
Tool executes inside wasmtime sandbox
|
|
↓
|
|
Network requests route through the network proxy
|
|
↓
|
|
Proxy validates domain against allowlist
|
|
↓
|
|
Proxy injects credentials from encrypted store
|
|
↓
|
|
Response returns to WASM module
|
|
↓
|
|
Tool output passes through Safety Layer
|
|
↓
|
|
LLM receives sanitized result
|
|
```
|
|
|
|
---
|
|
|
|
## Sandbox Architecture
|
|
|
|
### Fuel Metering
|
|
|
|
Every WASM instruction consumes "fuel." When a module runs out of fuel, it is terminated immediately. This prevents infinite loops and runaway computation.
|
|
|
|
```bash
|
|
# Configure fuel limit (default: 100,000,000 instructions)
|
|
export WASM_FUEL_LIMIT=100000000
|
|
```
|
|
|
|
### Memory Limits
|
|
|
|
WASM modules are allocated a fixed linear memory. Attempting to allocate beyond the limit traps and terminates the module.
|
|
|
|
```bash
|
|
# Configure memory limit (default: 16 MB)
|
|
export WASM_MEMORY_LIMIT=16777216
|
|
```
|
|
|
|
### Rate Limiting
|
|
|
|
Each WASM tool has a per-tool rate limiter to prevent a misbehaving or compromised tool from making excessive API calls.
|
|
|
|
Rate limits are declared in `capabilities.json`:
|
|
|
|
```json
|
|
{
|
|
"rate_limit": {
|
|
"requests_per_minute": 60,
|
|
"requests_per_day": 1000
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## capabilities.json
|
|
|
|
Every WASM tool must include a `capabilities.json` alongside its `.wasm` binary. This file is the single source of truth for what the tool is allowed to do.
|
|
|
|
```json
|
|
{
|
|
"name": "my-tool",
|
|
"version": "0.1.0",
|
|
"description": "Fetches data from example.com API",
|
|
|
|
"network": {
|
|
"allowed_hosts": [
|
|
"api.example.com",
|
|
"auth.example.com"
|
|
]
|
|
},
|
|
|
|
"filesystem": {
|
|
"read": ["/workspace/data/*"],
|
|
"write": ["/workspace/output/*"]
|
|
},
|
|
|
|
"credentials": [
|
|
{
|
|
"name": "example_api_key",
|
|
"inject_as": "Authorization",
|
|
"format": "Bearer {value}"
|
|
}
|
|
],
|
|
|
|
"rate_limit": {
|
|
"requests_per_minute": 30,
|
|
"requests_per_day": 500
|
|
}
|
|
}
|
|
```
|
|
|
|
### Network allowlist
|
|
|
|
The `network.allowed_hosts` list controls which domains the tool can reach. Requests to any domain not in this list are rejected by the network proxy before the TCP connection is established.
|
|
|
|
HTTPS traffic uses the `CONNECT` tunnel method. The proxy validates the target hostname against the allowlist before establishing the tunnel.
|
|
|
|
### Filesystem access
|
|
|
|
WASM tools cannot access the host filesystem by default. Paths declared under `filesystem.read` and `filesystem.write` are mounted into the WASM module's sandbox at the declared paths.
|
|
|
|
### Credential injection
|
|
|
|
Credentials listed in `capabilities.json` are never passed into the WASM module's memory. Instead, when the module makes an outbound HTTP request, the proxy intercepts the request and injects the specified header before forwarding it.
|
|
|
|
The WASM module never sees the raw credential value — it only makes an unauthenticated HTTP request, and the proxy adds the auth header transparently.
|
|
|
|
---
|
|
|
|
## Host Functions
|
|
|
|
WASM modules can call the following host functions provided by IronClaw:
|
|
|
|
| Function | Description |
|
|
|----------|-------------|
|
|
| `log(level, message)` | Write to the IronClaw log at the given severity level |
|
|
| `now_unix_secs()` | Return the current Unix timestamp |
|
|
| `workspace_read(path)` | Read a document from the workspace |
|
|
| `workspace_write(path, content)` | Write a document to the workspace |
|
|
|
|
These are the only host capabilities available. A WASM tool cannot call arbitrary OS functions, fork processes, or access the network directly — all network access goes through the proxy.
|
|
|
|
---
|
|
|
|
## Tool Discovery
|
|
|
|
WASM tools are discovered at startup from two locations:
|
|
|
|
- `~/.ironclaw/tools/` — User-installed tools
|
|
- `<workspace>/tools/` — Per-workspace tools
|
|
|
|
Each tool directory must contain:
|
|
- `<toolname>.wasm` — The compiled WebAssembly module
|
|
- `capabilities.json` — The capability declaration
|
|
|
|
---
|
|
|
|
## Installing WASM Tools
|
|
|
|
```bash
|
|
# Install from a local file
|
|
ironclaw tool install ./my-tool.wasm
|
|
|
|
# Install from a URL
|
|
ironclaw tool install https://example.com/tools/my-tool.wasm
|
|
|
|
# List installed tools
|
|
ironclaw tool list
|
|
```
|
|
|
|
Or via the `extension_install` tool in chat:
|
|
> "Install the tool from https://example.com/tools/my-tool.wasm"
|
|
|
|
---
|
|
|
|
## Module Compilation and Caching
|
|
|
|
WASM modules are compiled by wasmtime on first load and cached. Subsequent loads use the compiled artifact, so only the first invocation of a new tool incurs compilation overhead.
|
|
|
|
The cache is stored at `~/.ironclaw/wasm-cache/`.
|
|
|
|
---
|
|
|
|
## Security Notes
|
|
|
|
<Warning>
|
|
Review `capabilities.json` before installing any WASM tool from an untrusted source. The capability file determines exactly what the tool can access — network hosts, filesystem paths, and which credentials are injected.
|
|
</Warning>
|
|
|
|
<AccordionGroup>
|
|
<Accordion title="Credential injection is one-way" icon="lock">
|
|
The proxy injects credentials into outgoing requests. There is no mechanism for a WASM module to read stored secrets directly. Even if a WASM module is compromised, it cannot access the secrets store.
|
|
</Accordion>
|
|
|
|
<Accordion title="No process spawning" icon="shield">
|
|
WASM modules cannot spawn child processes, execute shell commands, or load dynamic libraries. The WASI interface exposed to modules is minimal.
|
|
</Accordion>
|
|
|
|
<Accordion title="Fuel prevents denial-of-service" icon="zap">
|
|
A buggy or malicious WASM tool that enters an infinite loop will be terminated when it exhausts its fuel allocation. This prevents a single tool from blocking the agent indefinitely.
|
|
</Accordion>
|
|
</AccordionGroup>
|