Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

Multi-Agent Sandbox

v1.0.0

Setup multi-agent sandbox infrastructure with Docker, Discord, SSH, and Tailscale. Use when: (1) creating a sandboxed agent for cross-gateway collaboration,...

0· 324·2 current·2 all-time
byErwan Lee Pesle@superworldsavior
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Suspicious
medium confidence
Purpose & Capability
The SKILL.md describes exactly the advertised purpose: creating Docker sandbox agents that communicate cross‑gateway via Discord, socat bridges, and Tailscale. The requested actions (adding SSH client to the image, creating socat bridges, configuring Tailscale, and per-agent allowlists) are consistent with that purpose. However, some required host actions (systemd services and firewall rules) are high privilege — they are explainable by the stated architecture but are substantial and should be expected only if you intend to modify host networking.
!
Instruction Scope
The runtime instructions direct the operator to perform host‑level changes: create systemd units, modify ufw rules, bind network listeners on the host's docker0 interface, and rebuild/force‑remove containers. They also instruct enabling powerful sandbox tools (exec, process, read, write, apply_patch, sessions_send, sessions_spawn). These steps go beyond simply configuring an isolated container and create persistent bridging paths between containers, host, VPS, and external gateways — increasing the risk of unintended data exposure or lateral access if misconfigured.
Install Mechanism
This is an instruction‑only skill (no install spec, no code files), so there is no automated download or archive extraction risk from the skill itself. The risk comes from the manual commands it instructs you to run on your systems.
!
Credentials
The skill requires external credentials and services in practice (Discord bot tokens, a Tailscale network, and a shared VPS) but declares no required environment variables in metadata. Asking operators to provision Discord bot tokens and Tailscale is reasonable for the described feature, but the skill also recommends enabling many powerful agent tools and cross‑agent allowlists, increasing the chance of sensitive data flow. The absence of declared env vars is an inconsistency that reduces transparency.
!
Persistence & Privilege
The instructions create long‑running host services (systemd socat units) and firewall rules that persist beyond a single agent session, establishing continuous network bridges between local containers, host, and a remote VPS. Although the skill is not flagged 'always:true', these persistent host changes effectively grant ongoing network access and increase the blast radius if an agent or image is compromised. The skill also advocates wide tool permissions (sessions_spawn, sessions_send) which can create long‑lived A2A channels.
What to consider before installing
This skill appears to do what it says, but it requires you to make host‑level, persistent changes (systemd services, firewall rules, network bridges) and to give sandbox agents many powerful capabilities (exec/process, sessions_send). Before installing: (1) only run this on a dedicated host or VM you control; do not use your main agent host; (2) restrict socat binds to the smallest necessary IPs and verify the exact unit files before enabling them; (3) use per‑agent Discord bot tokens with minimal scopes and do not reuse main agent credentials; (4) limit sandbox tool allowlists — remove exec/process or reduce workspace access if possible; (5) use Tailscale ACLs/exit node settings to restrict routes and audit connections; (6) rebuild and inspect the sandbox Docker image locally (avoid pulling unvetted images); and (7) log and monitor the created services and network flows so you can quickly revoke access. If you are unsure about any host commands or the source of this skill, ask the author for justification, a threat model, or a reviewed implementation before proceeding.

Like a lobster shell, security has layers — review code before you run it.

latestvk97e3vyn2cv3mx9sdajrjate5h82gwxd
324downloads
0stars
1versions
Updated 20h ago
v1.0.0
MIT-0

Multi-Agent Sandbox

Set up sandboxed agents that collaborate with agents from other OpenClaw gateways via Discord and a shared VPS, without exposing private data.

Architecture

Gateway A (Server A)                  Gateway B (Server B)
├── Main Agent (full access)          ├── Main Agent (full access)
│   agentToAgent.allow: ["*"]         │   agentToAgent.allow: ["*"]
└── Sandbox Agent (Docker)            └── Sandbox Agent (Docker)
    agentToAgent.allow: ["main"]          agentToAgent.allow: ["main"]
    ├── Discord ←── Shared Server ──→ Discord
    │                requireMention: true
    └── SSH ─→ socat ─→ Tailscale ─→ Shared VPS ←── SSH
                                      100.y.y.y

Three pillars: socat bridges (container → host → VPS), Tailscale mesh VPN (private networking), Discord + sessions_send (inter-agent communication).

Prerequisites

  • OpenClaw running with Docker sandbox support
  • Tailscale installed on all machines (server A + VPS + server B)
  • A Discord bot token per sandbox agent (https://discord.com/developers/applications)
  • A shared VPS accessible via Tailscale

Step 1 — Create the Sandbox Agent

Add to openclaw.json under agents.list:

{
  "id": "sandbox",
  "workspace": "/path/to/workspace-sandbox",
  "model": {
    "primary": "anthropic/claude-sonnet-4-6",
    "fallbacks": ["openai/gpt-4o"]
  },
  "identity": {
    "name": "Sandbox",
    "emoji": "📦"
  },
  "sandbox": {
    "mode": "all",
    "workspaceAccess": "rw",
    "sessionToolsVisibility": "all",
    "scope": "agent",
    "docker": {
      "image": "openclaw-sandbox:bookworm-slim",
      "readOnlyRoot": true,
      "network": "bridge",
      "memory": "1536m",
      "cpus": 2
    },
    "browser": { "enabled": true }
  },
  "tools": {
    "agentToAgent": {
      "allow": ["your-main-agent-id"]
    },
    "alsoAllow": ["message", "sessions_send", "sessions_list", "sessions_history"],
    "deny": ["gateway", "process", "whatsapp_login", "cron"],
    "sandbox": {
      "tools": {
        "allow": [
          "exec", "process", "read", "write", "edit", "apply_patch",
          "image", "web_search", "web_fetch",
          "sessions_list", "sessions_history", "sessions_send", "sessions_spawn",
          "subagents", "session_status", "message", "browser"
        ],
        "deny": [
          "canvas", "nodes", "gateway", "telegram", "irc", "googlechat",
          "slack", "signal", "imessage", "whatsapp_login", "cron"
        ]
      }
    }
  }
}

Key constraints:

  • sandbox.mode: "all" — all exec runs through Docker, never on host
  • readOnlyRoot: true — container filesystem is immutable except workspace
  • tools.deny — no gateway (can't modify config), no cron (can't schedule on host)
  • scope: "agent" — isolated container per agent (valid values: session | agent | shared)

Step 2 — A2A Permissions (Hub-Spoke Pattern)

Configure bidirectional communication using per-agent outbound allowlists (PR #39102):

{
  "tools": {
    "agentToAgent": { "enabled": true, "allow": ["*"] }
  },
  "agents": {
    "list": [
      {
        "id": "main-agent",
        "tools": { "agentToAgent": { "allow": ["*"] } }
      },
      {
        "id": "sandbox",
        "tools": { "agentToAgent": { "allow": ["main-agent"] } }
      }
    ]
  }
}

Result: sandbox → main-agent ✅ | sandbox → other-sandbox ❌ | main-agent → anyone

Both agents also need subagents.allowAgents for sessions_spawn:

// Main agent
"subagents": { "allowAgents": ["sandbox"] }

// Sandbox agent
"subagents": { "allowAgents": ["main-agent"] }

Must be set on BOTH agents. Forgetting one direction = silent "access denied" errors.

Step 3 — Add SSH to Docker Image

The default sandbox image lacks SSH. Edit Dockerfile.sandbox:

RUN apt-get update \
  && apt-get install -y --no-install-recommends \
    bash ca-certificates curl git jq \
    openssh-client \
    python3 ripgrep \
  && rm -rf /var/lib/apt/lists/*

Rebuild and force-recreate containers:

docker build -f Dockerfile.sandbox -t openclaw-sandbox:bookworm-slim .
docker ps --format "{{.ID}} {{.Image}}" | grep sandbox | awk '{print $1}' | xargs -r docker rm -f

Step 4 — Socat Bridges

Two bridges on each host. Always bind on 172.17.0.1 (docker0), never 0.0.0.0.

Bridge 1: Container → Gateway (local)

# /etc/systemd/system/socat-bridge-docker0-gateway.service
[Unit]
Description=Socat bridge: docker0 → Gateway
After=network.target docker.service

[Service]
Type=simple
ExecStart=/usr/bin/socat TCP-LISTEN:18789,bind=172.17.0.1,reuseaddr,fork TCP:127.0.0.1:18789
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Bridge 2: Container → VPS SSH (via Tailscale)

# /etc/systemd/system/socat-bridge-docker0-vps-ssh.service
[Unit]
Description=Socat bridge: docker0:2222 → VPS Tailscale SSH
After=network.target docker.service tailscaled.service
Wants=tailscaled.service

[Service]
Type=simple
ExecStart=/usr/bin/socat TCP-LISTEN:2222,bind=172.17.0.1,reuseaddr,fork TCP:100.y.y.y:22
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Enable, start, and open firewall:

sudo systemctl daemon-reload
sudo systemctl enable --now socat-bridge-docker0-gateway socat-bridge-docker0-vps-ssh
sudo ufw allow in on docker0 to 172.17.0.1 port 18789 proto tcp comment "socat-gateway"
sudo ufw allow in on docker0 to 172.17.0.1 port 2222 proto tcp comment "socat-vps-ssh"

The VPS bridge depends on Tailscale (Wants=tailscaled.service). Without this, socat tries to connect before the Tailscale interface exists — silent failure.

Step 5 — Discord Multi-Bot

Create a Discord bot

  1. https://discord.com/developers/applications → New Application
  2. Bot → Reset Token → copy
  3. Enable all 3 Privileged Gateway Intents (MESSAGE CONTENT, SERVER MEMBERS, PRESENCE)
  4. Invite: https://discord.com/oauth2/authorize?client_id=<APP_ID>&permissions=274878024704&scope=bot

Configure in openclaw.json

"discord": {
  "enabled": true,
  "accounts": {
    "default": {
      "enabled": true,
      "name": "Main Bot",
      "token": "$DISCORD_TOKEN_MAIN",
      "groupPolicy": "allowlist",
      "dmPolicy": "allowlist",
      "allowFrom": ["<YOUR_DISCORD_USER_ID>"],
      "guilds": {
        "<PRIVATE_GUILD_ID>": {
          "slug": "private",
          "requireMention": false
        }
      }
    },
    "sandbox": {
      "enabled": true,
      "name": "Sandbox Bot",
      "token": "$DISCORD_TOKEN_SANDBOX",
      "groupPolicy": "allowlist",
      "dmPolicy": "deny",
      "guilds": {
        "<SHARED_GUILD_ID>": {
          "slug": "shared",
          "requireMention": true
        }
      }
    }
  }
}

Agent routing bindings

"mappings": [
  {
    "agentId": "main-agent",
    "match": { "channel": "discord", "accountId": "default", "guildId": "<PRIVATE_GUILD_ID>" }
  },
  {
    "agentId": "sandbox",
    "match": { "channel": "discord", "accountId": "sandbox", "guildId": "<SHARED_GUILD_ID>" }
  }
]

requireMention: true is non-negotiable on shared guilds. Without it, two bots respond to each other = infinite loop + astronomical token bill.

Step 6 — Tailscale

Install on all machines:

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --ssh

The --ssh flag enables Tailscale SSH (identity-based auth, no keys to manage). For machines where you can't interactively authenticate:

# Generate auth key at https://login.tailscale.com → Settings → Keys
sudo tailscale up --authkey=tskey-auth-xxxxx --ssh

Do NOT install Tailscale inside the container. It requires NET_ADMIN capability, which defeats the sandbox purpose. Use socat bridges instead.

Step 7 — Sandbox Workspace

Create minimal workspace files:

mkdir -p /path/to/workspace-sandbox

SOUL.md — Define agent identity and constraints. TOOLS.md — Document SSH access: ssh -o StrictHostKeyChecking=no root@172.17.0.1 -p 2222

Communication Patterns

# Main → Sandbox (same gateway)
sessions_send(label="sandbox", message="...")

# Sandbox → Main (same gateway)
sessions_send(label="main-agent", message="...")

# Agent A → Agent B (different gateways)
# Only via Discord @mention. No sessions_send across gateways.

# Async collaboration
# Both agents SSH to VPS /workspace and use files.

Gotchas

  1. Container not using new image — After rebuilding Docker image, stop and remove old containers. OpenClaw reuses running containers.
  2. Cross-context messaging — Agent spawned from WhatsApp cannot write to Discord. First trigger must come from the right channel.
  3. MESSAGE CONTENT Intent — Must be enabled in Discord Developer Portal or bot receives empty messages.
  4. Socat silent timeout — If ssh -p 2222 hangs with no error, check UFW rules on docker0.
  5. Agent ID rename — Renaming an agent (e.g., sandboxspoke) breaks active sessions that reference the old ID. Add the old ID to agentToAgent.allow until those sessions expire.
  6. sessions_send timeouttimeoutSeconds: 0 for fire-and-forget, timeoutSeconds: 60 when waiting for a response. Timeout ≠ message not delivered.
  7. Bot token exposure — Never post tokens in Discord channels. If exposed, reset immediately via Developer Portal.

Comments

Loading comments...