T01 · Skill Instruction Hijacking
Error
- Location
- receiver_server.py:22
- Finding
- Unauthenticated Network Input Is Forwarded into the OpenClaw Agent Session<![CDATA[ ## Vulnerability Details **File Location**: `receiver_server.py:22-25, 33-48, 119-123, 196-207, 252-305`; `scripts/start.sh:8-10, 25-33` **Vulnerability Type**: Unauthenticated agent instruction injection **Risk Level**: High ### Vulnerable Code ```python RECEIVER_HOST = os.getenv("RECEIVER_HOST", "0.0.0.0") RECEIVER_PORT = int(os.getenv("RECEIVER_PORT", "8080")) RECEIVER_DIR = Path(os.getenv("RECEIVER_DIR", os.path.join(os.path.dirname(__file__), "../received"))) RECEIVER_SECRET = os.getenv("RECEIVER_SECRET", "") # optional secret ``` ```python def push_to_openclaw(text: str): queue_file = Path.home() / ".openclaw" / "workspace" / "received" / "message_queue.jsonl" queue_file.parent.mkdir(parents=True, exist_ok=True) entry = { "time": datetime.now().isoformat(), "text": text, } queue_file.append_text(json.dumps(entry, ensure_ascii=False) + "\n") log(f"Message written to queue: {queue_file}") _try_ws_push(text) ``` ```python def _check_secret(self) -> bool: if not RECEIVER_SECRET: return True auth = self.headers.get("Authorization", "") return auth == f"Bearer {RECEIVER_SECRET}" ``` ```python payload = _json.dumps({ "jsonrpc": "2.0", "method": "sessions.send", "params": { "text": text, }, "id": 1 }).encode("utf-8") ``` ```python def do_POST(self): if not self._check_secret(): self._error("Unauthorized", 401) return if self.path == "/upload": self._handle_upload() elif self.path == "/message": self._handle_message() elif self.path == "/webhook": self._handle_webhook() else: self._error("Unknown path", 404) ``` ```bash PORT="${RECEIVER_PORT:-8080}" HOST="${RECEIVER_HOST:-0.0.0.0}" SECRET="${RECEIVER_SECRET:-}" ARGs=(--port "$PORT" --host "$HOST") if [ -n "$SECRET" ]; then ARGs+=(--secret "$SECRET") fi python3 receiver_server.py "${ARGs[@]}" ``` ### Technical Analysis The re ...[truncated 2338 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Fail closed when no authentication secret is configured. Refuse to start on a non-loopback interface unless a strong secret or equivalent authentication mechanism is present. 2. Change the default host from `0.0.0.0` to `127.0.0.1`. 3. Generate a high-entropy credential during installation rather than relying on an optional environment variable. 4. Compare bearer tokens with `hmac.compare_digest()` and return a generic authorization failure. 5. Place the service behind TLS; bearer credentials transmitted over plaintext HTTP can otherwise be intercepted. 6. Apply per-client rate limiting, request quotas, and audit logging. 7. Mark all received content as untrusted external data using a structured envelope. Downstream Agent logic must not interpret it as system, developer, or operator instructions. 8. Require explicit operator approval before external content can initiate tool calls or privileged actions. 9. Consider disabling direct `sessions.send` forwarding and exposing received messages only through a quarantined review interface. 10. Update `scripts/start.sh` and `SKILL.md` so that authenticated, loopback-only operation is the documented and enforced default. ]]>
