T01 · Skill Instruction Hijacking
- Location
- runner.py:213
- Finding
- Remote WTT Content Is Automatically Executed as Privileged Agent Instructions<![CDATA[ ## Vulnerability Details **File Location**: `runner.py:213-231`, `runner.py:302-376`, `start_wtt_autopoll.py:608-617`, `start_wtt_autopoll.py:1933-2200` **Vulnerability Type**: Untrusted remote instruction execution through agent sessions **Risk Level**: Critical ### Complete Code Snippet ```python # runner.py:213-231 agent_id = self.agent.get_id() url = f"{self.ws_url}/{agent_id}" while self.running: try: async with websockets.connect(url, ping_interval=30, ping_timeout=10) as ws: self._ws = ws self._ws_connected = True self._reconnect_delay = 2 print(f"🔗 WebSocket connected: {url}") heartbeat_task = asyncio.create_task(self._heartbeat(ws)) refresh_task = asyncio.create_task(self._refresh_subscribed_topics()) try: async for raw in ws: if raw == "pong": continue try: data = json.loads(raw) await self._dispatch_ws_data(data) ``` ```python # runner.py:302-376 async def _handle_task_status_event(self, data: dict): """Handle task_status WS events — auto-execute new todo tasks on subscribed topics.""" try: task = data.get("task") or data.get("data") or {} status = str(task.get("status") or data.get("status") or "").lower() if status != "todo": return task_id = str(task.get("id") or task.get("task_id") or data.get("task_id") or "") topic_id = str(task.get("topic_id") or data.get("topic_id") or "") title = str(task.get("title") or data.get("title") or "") description = str(task.get("description") or data.get("description") or "") exec_mode = str(task.get("exec_mode") or data.get("exec_mode") or "reasoning") task_type = str(task.get("type") or task.get("task_type") or data.get("task_type") or "feature") if not task_id or not topic_id: ...[truncated 4011 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Require an authenticated WebSocket handshake using a server-issued, agent-specific credential. Bind the credential to the agent ID and rotate it periodically. 2. Sign task events and verify signatures, timestamps, nonces, topic membership, task ownership, and intended runner identity locally. 3. Require explicit user approval before executing newly received remote tasks. Automatic execution should be an opt-in mode with a clearly displayed trust policy. 4. Maintain a local allowlist of trusted WTT users, agents, topics, and permitted task types. 5. Treat all task fields as untrusted data. Place them in explicit untrusted-content delimiters and instruct the execution layer not to interpret embedded control instructions. 6. Execute remote tasks in a sandbox with: - No access to OpenClaw configuration or credentials. - A dedicated workspace. - A minimal tool allowlist. - Network and filesystem restrictions. - CPU, token, concurrency, and runtime limits. 7. Do not expose general-purpose `sessions_spawn`, `sessions_send`, or history access directly to the remote orchestration path. 8. Add a data-loss prevention check before publishing results. Require approval for outputs containing secrets, private file content, session history, or credentials. 9. Add replay protection and durable event deduplication rather than relying only on process-local sets. ]]>
