[ ⌘K ]
← BACK TO SEARCH

Good0007/openclaw-mcp

critical

将 [OpenClaw](https://openclaw.ai) Gateway WebSocket API 封装为 [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) 服务,让任何支持 MCP 的宿主(Claude Desktop、Cursor、VS Code Copilot Chat 等)可以直接与 OpenClaw 交互。

MCP server (purpose undetermined)

purpose: MCP server (purpose undetermined)threat: network exposed
TypeScript2May 20, 2026May 20, 2026GITHUB
5/20/2026
high1 finding
src/index.ts
360server.registerTool("config_get", {
361  description:
362    `Read a configuration value from the ${AGENT_NAME} gateway. ` +
363    'Pass an optional dot-notation key like "gateway.port" or "session.main" ' +
364    "to read a specific value, or leave empty to get the full config.",
365  inputSchema: {
366    key: z.string().optional().describe('Config key in dot notation, e.g. "gateway.port", "session.main"'),
367  },
368}, async ({ key }) => {
369    try {
370      const result = await rpc<Record<string, unknown>>("config.get", key ? { key } : {});
371      return jsonResult(result);
372    } catch (err) {
373      return textResult(`Error: ${fmtError(err)}`);
374    }
375  },
376);
377
378server.registerTool("config_set", {
379  description:
380    `Set a configuration value on the ${AGENT_NAME} gateway. ` +
381    "The value is parsed as JSON, so use quoted strings for string values.",
382  inputSchema: {
383    key: z.string().describe('Config key in dot notation, e.g. "session.main"'),
384    value: z.string().describe("JSON-encoded value, e.g. \"my-session\" or 18789 or true"),
385  },
386}, async ({ key, value }) => {
387    try {
388      let parsed: unknown;
389      try {
390        parsed = JSON.parse(value);
391      } catch {
392        parsed = value;
393      }
394      await rpc("config.set", { key, value: parsed });
395      return textResult(`Config ${key} updated.`);
396    } catch (err) {
397      return textResult(`Error: ${fmtError(err)}`);
398    }
399  },
400);
src/index.ts:360src/index.ts:383

// Network-exposed MCP server: any client can call these tools. Even with local-only threat model, a compromised LLM could exfiltrate secrets or modify config.

The MCP server exposes tools to read and write arbitrary configuration keys on the OpenClaw gateway. The config_get tool can retrieve the entire configuration (including sensitive values like tokens, passwords, API keys) when no key is specified. The config_set tool allows modifying any configuration value, potentially altering gateway behavior, security settings, or injecting malicious values. This goes beyond the intended purpose of sending chat messages and checking status.

ImpactAn attacker (or compromised LLM) can read all gateway configuration, including authentication tokens, passwords, API keys, and other secrets. They can also modify configuration to disable security, change endpoints, or inject malicious settings, leading to full compromise of the gateway and connected services.

FixRemove the config_get and config_set tools, or restrict them to a whitelist of non-sensitive keys. Never allow reading the full config or writing arbitrary keys. Consider using separate, purpose-built tools for any necessary configuration changes.

high1 finding
src/index.ts
383server.registerTool("config_set", {
384  description:
385    `Set a configuration value on the ${AGENT_NAME} gateway. ` +
386    "The value is parsed as JSON, so use quoted strings for string values.",
387  inputSchema: {
388    key: z.string().describe('Config key in dot notation, e.g. "session.main"'),
389    value: z.string().describe("JSON-encoded value, e.g. \"my-session\" or 18789 or true"),
390  },
391}, async ({ key, value }) => {
392    try {
393      let parsed: unknown;
394      try {
395        parsed = JSON.parse(value);
396      } catch {
397        parsed = value;
398      }
399      await rpc("config.set", { key, value: parsed });
400      return textResult(`Config ${key} updated.`);
401    } catch (err) {
402      return textResult(`Error: ${fmtError(err)}`);
403    }
404  },
405);
src/index.ts:383

// Exploitable via prompt injection if the MCP server is exposed to untrusted LLM prompts. In local-only setups, requires a compromised LLM to exploit.

The config_set tool allows setting arbitrary configuration keys on the gateway with no restrictions on which keys can be modified. An attacker who can send prompts to the MCP server (e.g., via prompt injection) could change critical gateway settings such as authentication tokens, API keys, or session configurations, potentially leading to privilege escalation or service disruption.

ImpactAn attacker could modify gateway configuration to disable authentication, change AI provider credentials, or alter session behavior, leading to unauthorized access or denial of service.

FixRestrict config_set to a whitelist of safe configuration keys, or require additional authorization for sensitive keys. Alternatively, remove the tool if not essential.

high1 finding
src/index.ts
360server.registerTool("config_get", {
361  description: `Read a configuration value from the ${AGENT_NAME} gateway. ...`,
362  inputSchema: { key: z.string().optional().describe('Config key in dot notation') },
363}, async ({ key }) => {
364    try {
365      const result = await rpc<Record<string, unknown>>("config.get", key ? { key } : {});
366      return jsonResult(result);
367    } catch (err) {
368      return textResult(`Error: ${fmtError(err)}`);
369    }
370  },
371);
372
373server.registerTool("config_set", {
374  description: `Set a configuration value on the ${AGENT_NAME} gateway. ...`,
375  inputSchema: { key: z.string(), value: z.string() },
376}, async ({ key, value }) => {
377    try {
378      let parsed: unknown;
379      try { parsed = JSON.parse(value); } catch { parsed = value; }
380      await rpc("config.set", { key, value: parsed });
381      return textResult(`Config ${key} updated.`);
382    } catch (err) {
383      return textResult(`Error: ${fmtError(err)}`);
384    }
385  },
386);
src/index.ts:360src/index.ts:383

// Network-exposed MCP server: any client with access to the MCP can exploit this. Even in local-only scenarios, a compromised LLM could exfiltrate secrets.

The config_get and config_set tools allow reading and writing arbitrary configuration keys on the OpenClaw gateway. The gateway configuration likely contains sensitive settings such as API keys, tokens, passwords, and other credentials. An attacker with access to these tools can exfiltrate secrets or modify configuration to weaken security (e.g., disable authentication).

ImpactAn attacker could read all gateway configuration including credentials, API keys, and tokens, or modify configuration to gain persistent access, disable security controls, or pivot to other systems.

FixRestrict config_get/config_set to a whitelist of non-sensitive keys, or remove these tools entirely if not essential. If needed, require explicit confirmation or additional authorization for sensitive operations.

high2 findings
src/index.ts
224server.registerTool("send_message", {
225  description:
226    `Send a message through a specific ${AGENT_NAME} channel (Telegram, Discord, Slack, etc.) ` +
227    "to a recipient. This sends the message directly without triggering AI.",
228  inputSchema: {
229    channel: z.string().describe('Channel name, e.g. "telegram", "discord", "slack", "signal", "whatsapp"'),
230    to: z.string().describe("Recipient identifier (phone number, user ID, channel name, etc."),
231    message: z.string().describe("Message text to send"),
232  },
233}, async ({ channel, to, message }) => {
234    try {
235      await rpc("send", { channel, to, message });
236      return textResult(`Message sent to ${to} via ${channel}.`);
237    } catch (err) {
238      return textResult(`Error: ${fmtError(err)}`);
239    }
240  },
241);
high1 finding
src/index.ts
224server.registerTool("send_message", {
225  description: `Send a message through a specific ${AGENT_NAME} channel (Telegram, Discord, Slack, etc.) to a recipient. ...`,
226  inputSchema: {
227    channel: z.string().describe('Channel name, e.g. "telegram", "discord", "slack", "signal", "whatsapp"'),
228    to: z.string().describe("Recipient identifier (phone number, user ID, channel name, etc.)"),
229    message: z.string().describe("Message text to send"),
230  },
231}, async ({ channel, to, message }) => {
232    try {
233      await rpc("send", { channel, to, message });
234      return textResult(`Message sent to ${to} via ${channel}.`);
235    } catch (err) {
236      return textResult(`Error: ${fmtError(err)}`);
237    }
238  },
239);
src/index.ts:224

// Network-exposed MCP server: any client can send messages. Even locally, a compromised LLM could abuse this.

The send_message tool allows sending arbitrary messages to any recipient via any configured channel (Telegram, Discord, Slack, Signal, WhatsApp, etc.) without any restrictions. An attacker could use this to send phishing messages, spam, or malicious content impersonating the user or the AI agent.

ImpactAn attacker could send fraudulent messages to contacts, spread misinformation, perform social engineering attacks, or incur costs (e.g., SMS fees). The tool provides no rate limiting, recipient whitelist, or content validation.

FixRestrict the send_message tool to a whitelist of allowed recipients or channels, add rate limiting, require confirmation for external messaging, or remove the tool if not essential.

medium1 finding
src/index.ts
224server.registerTool("send_message", {
225  description:
226    `Send a message through a specific ${AGENT_NAME} channel (Telegram, Discord, Slack, etc.) ` +
227    "to a recipient. This sends the message directly without triggering AI.",
228  inputSchema: {
229    channel: z
230      .string()
231      .describe('Channel name, e.g. "telegram", "discord", "slack", "signal", "whatsapp"'),
232    to: z.string().describe("Recipient identifier (phone number, user ID, channel name, etc.)"),
233    message: z.string().describe("Message text to send"),
234  },
235}, async ({ channel, to, message }) => {
236    try {
237      await rpc("send", { channel, to, message });
238      return textResult(`Message sent to ${to} via ${channel}.`);
239    } catch (err) {
240      return textResult(`Error: ${fmtError(err)}`);
241    }
242  },
243);
src/index.ts:224

// Exploitable via prompt injection if the MCP server is exposed to untrusted LLM prompts. In local-only setups, requires a compromised LLM to exploit.

The send_message tool allows sending arbitrary messages to any recipient via any configured channel without restrictions. An attacker could use this to send spam, phishing messages, or other malicious content through the gateway's messaging channels.

ImpactAn attacker could abuse the tool to send unauthorized messages, potentially leading to social engineering attacks, spam, or reputational damage.

FixRestrict the tool to a whitelist of allowed channels and recipients, or require explicit user confirmation before sending. Consider rate-limiting or logging all sent messages.

medium1 finding
src/index.ts
360server.registerTool("config_get", {
361  description:
362    `Read a configuration value from the ${AGENT_NAME} gateway. ` +
363    'Pass an optional dot-notation key like "gateway.port" or "session.main" ' +
364    "to read a specific value, or leave empty to get the full config.",
365  inputSchema: {
366    key: z
367      .string()
368      .optional()
369      .describe('Config key in dot notation, e.g. "gateway.port", "session.main"'),
370  },
371}, async ({ key }) => {
372    try {
373      const result = await rpc<Record<string, unknown>>("config.get", key ? { key } : {});
374      return jsonResult(result);
375    } catch (err) {
376      return textResult(`Error: ${fmtError(err)}`);
377    }
378  },
379);
src/index.ts:360

// Exploitable via prompt injection if the MCP server is exposed to untrusted LLM prompts. In local-only setups, requires a compromised LLM to exploit.

The config_get tool allows reading any configuration value from the gateway, including potentially sensitive information such as API keys, tokens, or passwords stored in the gateway configuration. An attacker could exfiltrate these secrets.

ImpactAn attacker could read sensitive configuration data, leading to credential exposure and further compromise of the gateway or connected services.

FixRestrict config_get to non-sensitive keys, or mask sensitive values in the response. Consider removing the tool if not essential.

medium1 finding
src/index.ts
438server.registerTool("session_reset", {
439  description: "Reset (clear) the conversation history of a session. This creates a fresh conversation context.",
440  inputSchema: {
441    session_key: z.string().optional().describe(`Session key to reset (default: "${DEFAULT_SESSION}")`),
442    confirm: z.boolean().describe("Must be true to confirm the destructive reset operation"),
443  },
444}, async ({ session_key, confirm }) => {
445    if (!confirm) {
446      return textResult("Aborted: set confirm=true to reset the session history.");
447    }
448    try {
449      await rpc("sessions.reset", { sessionKey: session_key ?? DEFAULT_SESSION });
450      return textResult(`Session "${session_key ?? DEFAULT_SESSION}" has been reset.`);
451    } catch (err) {
452      return textResult(`Error: ${fmtError(err)}`);
453    }
454  },
455);
src/index.ts:438

// Network-exposed MCP server: any client can reset sessions. Local-only: compromised LLM could cause data loss.

The session_reset tool allows clearing conversation history for any session. While it requires a confirm flag, this is trivially bypassed by an attacker (just set confirm=true). An attacker could destroy valuable conversation history, causing loss of context or data.

ImpactAn attacker could delete conversation history for any session, potentially causing loss of important information or disrupting ongoing interactions.

FixConsider removing the session_reset tool or adding additional authorization (e.g., require a separate confirmation step or restrict to specific sessions).

medium1 finding
src/index.ts
438server.registerTool("session_reset", {
439  description:
440    "Reset (clear) the conversation history of a session. " +
441    "This creates a fresh conversation context.",
442  inputSchema: {
443    session_key: z.string().optional().describe(`Session key to reset (default: "${DEFAULT_SESSION}")`),
444    confirm: z.boolean().describe("Must be true to confirm the destructive reset operation"),
445  },
446}, async ({ session_key, confirm }) => {
447    if (!confirm) {
448      return textResult("Aborted: set confirm=true to reset the session history.");
449    }
450    try {
451      await rpc("sessions.reset", {
452        sessionKey: session_key ?? DEFAULT_SESSION,
453      });
454      return textResult(`Session "${session_key ?? DEFAULT_SESSION}" has been reset.`);
455    } catch (err) {
456      return textResult(`Error: ${fmtError(err)}`);
457    }
458  },
459);
src/index.ts:438

// Network-exposed MCP server: any client can reset sessions. Even with local-only threat model, a compromised LLM could abuse this.

The session_reset tool allows clearing conversation history for any session. While it requires a confirm flag, this is easily bypassed by an LLM or attacker. This is a destructive action that can cause loss of conversation context and potentially disrupt ongoing interactions.

ImpactAn attacker can reset any session's history, causing denial of service or loss of important context. This could be used to cover tracks after malicious activity.

FixRemove the session_reset tool or restrict it to specific sessions with additional authentication. Consider adding rate limiting and logging.

medium1 finding
src/index.ts
224server.registerTool("send_message", {
225  description: ...,
226  inputSchema: {
227    channel: z.string().describe('Channel name, e.g. "telegram", "discord", "slack", "signal", "whatsapp"'),
228    to: z.string().describe("Recipient identifier (phone number, user ID, channel name, etc.)"),
229    message: z.string().describe("Message text to send"),
230  },
231}, async ({ channel, to, message }) => {
232    try {
233      await rpc("send", { channel, to, message });
234      ...
235    } catch (err) {
236      return textResult(`Error: ${fmtError(err)}`);
237    }
238  },
239);
src/index.ts:224

// Network-exposed MCP server: any client can send arbitrary inputs.

The send_message tool accepts arbitrary strings for channel and recipient without any validation. An attacker could provide unexpected values that might cause errors, trigger unintended behavior, or be used for injection attacks against the gateway.

ImpactPotential for injection attacks against the gateway's messaging subsystem, or causing unexpected behavior by providing malformed channel names or recipient identifiers.

FixValidate channel against a list of known channels, and validate recipient format (e.g., phone number regex, user ID pattern).

low1 finding
src/index.ts
102server.registerTool("chat_send", {
103  description:
104    `Send a message to ${AGENT_NAME} and wait for the complete AI response. ` +
105    ...
106  inputSchema: {
107    message: z.string().describe("The message to send to the AI agent"),
108    session_key: z.string().optional().describe(`Session key (default: "${DEFAULT_SESSION}")`),
109    thinking: z.enum(["auto", "low", "medium", "high"]).optional().describe("AI thinking budget (default: auto)"),
110    timeout_seconds: z.number().int().min(5).max(600).optional().describe("Max wait time in seconds (default: 300)"),
111  },
112}, async ({ message, session_key, thinking, timeout_seconds }) => {
113    try {
114      const result = await chatSend(gateway, {
115        sessionKey: session_key ?? DEFAULT_SESSION,
116        message,
117        thinking: thinking ?? undefined,
118        timeoutMs: (timeout_seconds ?? 300) * 1000,
119      });
120      ...
121    }
122  },
123);
src/index.ts:102

// Exploitable via prompt injection if the MCP server is exposed to untrusted LLM prompts. In local-only setups, requires a compromised LLM to exploit.

The chat_send tool does not validate the length or content of the message parameter. An attacker could send extremely long messages or messages containing special characters that might cause denial of service or trigger unexpected behavior in the AI agent or gateway.

ImpactPotential denial of service by sending excessively long messages, or injection of special characters that could cause parsing errors or unexpected AI behavior.

FixAdd input validation to limit message length (e.g., max 10000 characters) and sanitize or reject messages with control characters.

shell.execenv.exposure
100
LLM-based
low findings+5
high findings+125
medium findings+90
scoringcompleted