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)
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);// 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.
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);// 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.
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);// 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.
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);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);// 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.
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);// 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.
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);// 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.
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);// 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).
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);// 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.
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);// 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).
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);// 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.