Back to skill

Security audit

OpenClaw WeCom Channel

Security checks for vulnerabilities and agentic risk

Overview

This WeCom channel appears purpose-built for messaging, but its documented pairing access control is not enforced before messages are authorized to the agent.

Review this before installing in a real workspace. Use allowlist mode rather than pairing until pairing enforcement is fixed, expose only the intended callback endpoint behind rate and body-size limits, and avoid routing privileged agents or sensitive tools through this channel unless you are comfortable with any WeCom app user reaching the agent under the current authorization behavior.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
src/bot.ts:82
Finding

Pairing Policy Bypass and Unconditional Command Authorization

Content
View full analysis
String(entry)); if (dmPolicy === "allowlist") { const allowed = allowFrom.some( (id) => id.toLowerCase() === ctx.userId.toLowerCase(), ); if (!allowed) { log(`wecom[${account.accountId}]: 用户 ${ctx.userId} 不在白名单中,忽略`); return; } } ``` ```ts const ctxPayload = core.channel.reply.finalizeInboundContext({ Body: body, RawBody: ctx.content, CommandBody: ctx.content, From: wecomFrom, To: wecomTo, SessionKey: route.sessionKey, AccountId: route.accountId, ChatType: "direct" as const, SenderName: ctx.userId, SenderId: ctx.userId, Provider: "wecom" as const, Surface: "wecom" as const, MessageSid: ctx.msgId, Timestamp: ctx.createTime * 1000, WasMentioned: false, CommandAuthorized: true, OriginatingChannel: "wecom" as const, OriginatingTo: wecomTo, }); ``` ### Technical Analysis The plugin advertises three direct-message policies: `open`, `pairing`, and `allowlist`. However, the inbound authorization logic only implements the `allowlist` branch. When `dmPolicy` is set to `pairing`, an unknown sender falls through to normal agent dispatch without any pairing request, approval lookup, or rejection. This behavior contradicts the documented guarantee that unknown users in pairing mode require a pairing code and administrator approval. The problem is compounded by setting `CommandAuthorized: true` for every message that reaches dispatch. This value is not derived from the configured policy or a verified pairing state. Consequently, an unpaired sender is represented to the OpenClaw runtime as authorized to issue commands. Cryptographic callback verification does not mitigate this a ...[truncated 1740 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/monitor.ts:26
Finding

Unbounded HTTP Callback Body Enables Remote Resource Exhaustion

Content
View full analysis
{ return new Promise((resolve, reject) => { const chunks: Buffer[] = []; req.on("data", (chunk: Buffer) => chunks.push(chunk)); req.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8"))); req.on("error", reject); }); } ``` The unbounded reader is invoked for public POST callbacks at `src/monitor.ts:126`: ```ts const body = await readRequestBody(req); ``` ### Technical Analysis The callback endpoint is intended to be publicly reachable, commonly through a tunnel or reverse proxy. For every POST request, the server accumulates all received chunks in an in-memory array and then creates another combined buffer with `Buffer.concat`. No maximum body size is enforced through `Content-Length` validation or streamed byte counting. Signature verification and XML extraction happen only after the entire request body has been read. Therefore, an attacker does not need a valid WeCom signature or knowledge of callback credentials to consume memory. A slowly streamed request can also retain a connection and its accumulated buffers for an extended period because the server does not configure request timeouts in the reviewed code. ### Attack Path 1. An attacker discovers or is given the public callback URL. 2. The attacker opens one or more POST connections to the endpoint. 3. The attacker sends an oversized body or continuously streams data without completing the request. 4. The server appends every chunk to the `chunks` array before performing authentication. 5. Multiple concurrent requests increase memory and connection consumption. 6. The Node.js process becomes unresponsive, experiences garbage-collection pressure, or terminates due to memory exhaustion. 7. Legitimate W ...[truncated 693 chars]
Remediation
View remediation
{ return new Promise((resolve, reject) => { const declaredLength = Number(req.headers["content-length"] ?? 0); if (declaredLength > MAX_BODY_BYTES) { reject(new Error("Request body too large")); req.destroy(); return; } const chunks: Buffer[] = []; let totalBytes = 0; req.on("data", (chunk: Buffer) => { totalBytes += chunk.length; if (totalBytes > MAX_BODY_BYTES) { reject(new Error("Request body too large")); req.destroy(); return; } chunks.push(chunk); }); req.on("end", () => { resolve(Buffer.concat(chunks, totalBytes).toString("utf-8")); }); req.on("error", reject); }); } ``` 2. Return HTTP `413 Payload Too Large` when the limit is exceeded rather than treating the condition as an internal server error. 3. Configure request, header, keep-alive, and connection timeouts on the HTTP server to mitigate slow-body attacks. 4. Apply request-rate and concurrent-connection limits at the reverse proxy or tunnel layer. 5. Restrict accepted callback paths and content types. The current server processes GET and POST requests regardless of pathname. 6. Monitor rejected body sizes, connection counts, and repeated failures without logging complete request bodies or sensitive query parameters. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (18)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The entire skill documentation is presented only in Chinese, including setup steps, warnings, and operational instructions, with no indication that users may choose another language or that the skill is intentionally limited to a Chinese-speaking audience. Under the policy rule, forcing a specific language without opt-in is a natural-language locale violation.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 18)May include surrounding context.

或手动复制:

bash
mkdir -p ~/.openclaw/extensions/wecom
cp -r . ~/.openclaw/extensions/wecom/

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 18)May include surrounding context.

或手动复制:

bash
mkdir -p ~/.openclaw/extensions/wecom
cp -r . ~/.openclaw/extensions/wecom/

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill metadata explicitly declares network capability in metadata.openclaw.requires.network, but it does not declare an explicit tool scope such as permissions or allowed-tools. That creates an authorization ambiguity where a host may permit broader runtime behavior than users expect, which is especially relevant for a messaging channel plugin that handles inbound and outbound traffic.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The configuration example includes real secret-bearing fields such as secret, token, and encodingAESKey without any warning about secure handling, redaction, or avoiding commits to source control. In practice, users often copy examples verbatim into config files, screenshots, issues, or repositories, which can lead to credential exposure and compromise of the WeCom integration.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The documentation instructs users to expose a local callback service to the public internet through Cloudflare Tunnel, but it does not warn about authentication, source validation, rate limiting, or minimizing exposure. Since this plugin receives inbound messages and callback traffic, an internet-exposed endpoint increases the attack surface for spoofed requests, denial-of-service, and misconfiguration-driven unauthorized access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The code enqueues a system event containing a preview derived from the user's message content, which propagates user text into internal event pipelines beyond the original chat channel. In this plugin context, that is more dangerous because enterprise WeCom messages may contain confidential corporate data, and system events are often broadly visible to observability, audit, or orchestration components that users do not expect to receive their full or partial message content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

The sendText path transmits message content and recipient information via sendMessageWecom, which is a network operation that may disclose user or system data. In this file there is no confirmation prompt, logging, or user-facing comment/docstring warning about that transmission.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

When media upload is unsupported, the adapter silently falls back to sending the raw media URL as text to WeCom. If media URLs contain sensitive query parameters, pre-signed access tokens, internal hostnames, or references to private storage, this can leak secrets or internal resource locations to recipients and downstream logging systems.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This function sends the recipient identifier and message text to the external WeCom API via an HTTP POST request. While the code has internal comments describing the API usage, it does not include any user-facing confirmation, logging, or warning that user-provided content and identifiers will be transmitted off-system.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: openclaw has 16 known advisory(ies) (CVE-2026-53846 (OpenClaw: Workspace .env npm_execpath could influence bundled runtime dependency); CVE-2026-32064 (OpenClaw's andbox browser noVNC observer lacked VNC authentication); CVE-2026-32006 (OpenClaw has a BlueBubbles group allowlist mismatch via DM pairing-store fallbac) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

This TypeScript file uses Chinese-only natural-language comments and descriptions such as "企业微信账号管理" and related function documentation, with no indication that the skill offers language choice or that the locale restriction is explicitly justified. The policy requires flagging language or locale constraints when they are imposed without user opt-in.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code logs inbound WeCom message content directly, including up to the first 100 characters of user-supplied text. In an enterprise messaging integration, message bodies commonly contain personal data, credentials, internal business information, or other sensitive content, so writing them to application logs can create an unnecessary secondary data store accessible to operators, log processors, or downstream SIEM systems.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

This file includes user-facing natural-language strings such as the plugin description, selection label, and blurb in fixed Chinese/English text. Under the stated policy, forcing a specific language or locale without user opt-in is a natural-language policy concern unless the locale constraint is explicitly justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

This TypeScript file uses Chinese-only natural-language documentation and later emits Chinese-only runtime messages, which imposes a specific language/locale on operators and maintainers. The file does not indicate that the skill is region-specific or that users can choose another language, so it matches the language-policy violation criterion.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

Thrown errors at these lines are natural-language strings surfaced to users or operators, and they are written only in Chinese. Because the file does not offer locale choice or explain a justified regional restriction, this forces a specific language without opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

Multiple log and error messages in this range are emitted only in Chinese, affecting runtime observability and operator interaction. Without an explicit region-specific justification or an option to select language, this is a natural-language locale policy issue.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The file's human-readable comments and thrown error messages are written only in Chinese, which can impose a fixed language on users or operators. There is no indication that the skill is region-specific or that users can opt into this locale, so it may conflict with language-choice policy expectations.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.