Back to skill

Security audit

WeChat Work OpenClaw Adapter

Security checks for vulnerabilities and agentic risk

Overview

This skill has a coherent WeChat Work to OpenClaw purpose, but its webhook security and secret/message handling are under-scoped for an internet-reachable enterprise messaging bridge.

Review before installing. Use only in a controlled test environment unless the webhook is fixed to require signatures, reject stale or replayed requests, bind to loopback by default, restrict logs and .env permissions, and use pinned dependencies. Treat the adapter as handling sensitive enterprise chat content and credentials.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (6)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/index.js:137
Finding

Webhook Signature Verification Can Be Bypassed When Authentication Parameters Are Missing

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/index.js:121
Finding

Authenticated Webhook Messages Can Be Replayed Without Deduplication or Freshness Enforcement

Content
View full analysis
{ try { const { msg_signature, timestamp, nonce } = req.query; const rawXml = req.body; // ... if (msg_signature && timestamp && nonce) { const arr = [WEBHOOK_TOKEN, timestamp, nonce, encrypt].sort(); const tmpStr = arr.join(''); const sha1 = crypto.createHash('sha1').update(tmpStr).digest('hex'); if (sha1 !== msg_signature) { log('WARN', `❌ POST 签名验证失败:计算=${sha1}, 收到=${msg_signature}`); return res.status(200).send('success'); } log('INFO', '✅ POST 签名验证成功'); } // ... res.status(200).send('success'); (async () => { try { log('INFO', `🤖 调用 OpenClaw...`); const claudeReply = await callOpenClaw(content); const accessToken = await getAccessToken(); await axios.post( `https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=${accessToken}`, { touser: fromUser, msgtype: 'text', agentid: parseInt(AGENT_ID), text: { content: claudeReply }, } ); log('INFO', `✅ 回复已发送 to=${fromUser}`); } catch (err) { log('ERROR', `❌ 异步回复失败: ${err.message}`); } })(); ``` ### Technical Analysis A valid signature proves that the request parameters and encrypted body were signed with the configured webhook token, but it does not prove that the request is fresh. The handler does not: - Check whether `timestamp` falls within an acceptable time window. - Record and reject reused signatures or nonces. - Extract and deduplicate the WeCom `MsgId`. - Apply per-user, per-source, or global rate limits. The asynchronous processing pattern means every accepted copy can independently invoke OpenClaw and the We ...[truncated 1193 chars]
Remediation
View remediation
300) { return res.status(403).send('Expired request'); } ``` Deduplication should use an authenticated message identifier and an expiration time at least as long as the accepted replay window. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/deploy.sh:34
Finding

Deployment Creates a Multi-Secret Environment File Without Enforcing Restrictive Permissions

Content
View full analysis
"$TARGET_DIR/.env" << 'EOF' # === WeChat Work Credentials === CORP_ID=your_corp_id AGENT_ID=your_agent_id AGENT_SECRET=your_encoding_aes_key_43chars APP_SECRET=your_app_secret_for_access_token WEBHOOK_TOKEN=your_webhook_token # === OpenClaw === OPENCLAW_TOKEN=your_openclaw_bearer_token OPENCLAW_BASE_URL=http://localhost:18789 CLAUDE_MODEL=claude-haiku-4-5 EOF echo "📝 Created .env template at $TARGET_DIR/.env — edit with your credentials" fi ``` ### Technical Analysis The deployment creates `.env` without setting a restrictive umask or explicitly applying mode `0600`. The resulting permissions depend on the invoking user's environment. With a common umask of `022`, the file may be created as `0644`, making it readable by other local users. The file is intended to contain: - The WeCom EncodingAESKey. - The application secret used to obtain access tokens. - The webhook authentication token. - The OpenClaw bearer token. Although `references/security-guide.md` recommends `chmod 600`, the deployment script does not enforce that recommendation. The highlighted instruction in `SKILL.md` to edit `~/wecom-adapter/.env` is necessary for the declared integration, but the storage mechanism is not hardened to the minimum privilege required. ### Attack Path 1. A user runs `deploy.sh` under a permissive umask. 2. The script creates `.env` with group-readable or world-readable permissions. 3. The user inserts production credentials as instructed. 4. Another local account, process, backup agent, or compromised service reads the file. 5. The recovered credentials are used to call OpenClaw, authenticate webhook messages, decrypt captured WeCom traffic, or obtain WeCom access tokens. ### Impact Asses ...[truncated 620 chars]
Remediation
View remediation
"$TARGET_DIR/.env" << 'EOF' # Environment template EOF fi chmod 600 "$TARGET_DIR/.env" chmod 700 "$TARGET_DIR" "$TARGET_DIR/logs" ``` Also: 1. Refuse to start if `.env` is group-readable or world-readable. 2. Add `.env` to a packaged `.gitignore`. 3. Prefer a platform secret manager for production deployments. 4. Run the adapter as a dedicated unprivileged operating-system account. 5. Rotate all credentials if insecure permissions are discovered. 6. Avoid exposing secret-bearing directories to broad backup or synchronization tools. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/index.js:158
Finding

Sensitive User Messages and Model Responses Are Persisted in Plaintext Logs

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/index.js:299
Finding

Adapter Listens on All Network Interfaces Despite Localhost-Only Security Claims

Content
View full analysis
{ log('INFO', `🚀 WeCom 适配器启动成功,监听 :${port}`); log('INFO', `📝 日志位置: ${logsDir}/wecom-adapter.log`); log('INFO', `🤖 使用模型: ${CLAUDE_MODEL}`); }); ``` ### Technical Analysis No host argument is supplied to `app.listen`. In a typical Node.js deployment, this causes the server to listen on an unspecified address and accept connections through available network interfaces rather than restricting it to loopback. This conflicts with `references/security-guide.md`, which states that the adapter binds to `localhost:8090` and is accessible only through the Cloudflare Tunnel. The declared workflow requires the tunnel to connect to a local service. It does not require the adapter to accept direct LAN or internet traffic. Binding to all interfaces therefore exceeds the minimum network privilege necessary for the declared functionality. ### Attack Path 1. The adapter runs on a machine whose firewall allows inbound access to port 8090. 2. An attacker on the same network—or the internet, depending on routing and firewall configuration—connects directly to the host. 3. The attacker bypasses any controls, monitoring, or access policy associated with the intended Cloudflare Tunnel path. 4. The attacker directly probes `/health` and `/webhook`. 5. The attacker combines direct reachability with the authentication-bypass or replay weaknesses to trigger unauthorized processing. ### Impact Assessment This exposure: - Expands the webhook attack surface beyond the intended tunnel. - Allows direct reconnaissance of service availability. - Increases the number of parties able to exploit request-processing weaknesses. - May expose the endpoint on local wireless, office, container, or cloud networks. - Undermines the documented network-isolation model. It does not ...[truncated 164 chars]
Remediation
View remediation
{ log('INFO', `Adapter listening on ${host}:${port}`); }); ``` Additionally: 1. Make broader network binding an explicit, documented opt-in. 2. Configure host firewalls to reject direct access to port 8090. 3. Verify the actual listening address during deployment with `ss`, `netstat`, or an equivalent tool. 4. Update the security guide so its network claims match the implementation. 5. If direct exposure is necessary, place the adapter behind a hardened reverse proxy with TLS, request-size limits, rate limiting, and source restrictions. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/deploy.sh:13
Finding

Deployment Installs Non-Reproducible Dependency Versions Without a Reviewed Lockfile

Content
View full analysis
"$TARGET_DIR/package.json" << 'EOF' { "name": "wecom-adapter", "version": "1.0.0", "type": "module", "scripts": { "start": "node --tls-min-v1.2 index.js" }, "dependencies": { "express": "^4.21.2", "axios": "^1.8.4", "xml2js": "^0.6.2", "dotenv": "^16.4.7" } } EOF fi ``` ```bash # Install dependencies cd "$TARGET_DIR" npm install ``` ### Technical Analysis The generated `package.json` uses caret ranges, allowing deployment to resolve package versions newer than those visible during the audit. The project does not package a reviewed `package-lock.json`, and deployment uses `npm install` rather than a lockfile-enforcing installation command. As a result: - Different deployments may install different dependency versions. - Future releases within allowed ranges are trusted without review. - Transitive dependencies are not fixed to audited versions. - Package lifecycle scripts can execute during installation. - The effective code installed on a target system can change after the Skill itself has been reviewed. No malicious package, typosquatting, or dependency confusion was confirmed in the reviewed dependency names. The vulnerability is the unsafe and non-reproducible installation process. ### Attack Path 1. A permitted dependency or transitive dependency publishes a compromised or unexpectedly vulnerable release within the accepted version range. 2. A user later runs `deploy.sh`. 3. `npm install` resolves the newer release because no reviewed lockfile constrains it. 4. The package or a transitive package is installed and may execute lifecycle scripts. 5. Compromised dependency code runs during insta ...[truncated 639 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (20)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The documented behavior diverges from the described purpose in several security-relevant ways: undeclared local logging of message content, permissive CORS, an extra HTTP endpoint, and confusing secret usage for cryptography. This is dangerous because operators may deploy the skill under false assumptions, exposing message data, widening network attack surface, and misconfiguring cryptographic verification.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 14)May include surrounding context.

md
# 1. Deploy
bash <skill_dir>/scripts/deploy.sh

# 2. Edit .env with your WeChat Work credentials
nano ~/wecom-adapter/.env

# 3. Start

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 15)May include surrounding context.

md
# 1. Deploy
bash <skill_dir>/scripts/deploy.sh

# 2. Edit .env with your WeChat Work credentials
nano ~/wecom-adapter/.env

# 3. Start

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/setup-guide.md (reported line 29)May include surrounding context.

md
# 1. Deploy
bash <skill_dir>/scripts/deploy.sh

# 2. Edit .env with your WeChat Work credentials
nano ~/wecom-adapter/.env

# 3. Start

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/setup-guide.md (reported line 46)May include surrounding context.

md
# 1. Deploy
bash <skill_dir>/scripts/deploy.sh

# 2. Edit .env with your WeChat Work credentials
nano ~/wecom-adapter/.env

# 3. Start

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/deploy.sh (reported line 34)May include surrounding context.

sh
# 1. Deploy
bash <skill_dir>/scripts/deploy.sh

# 2. Edit .env with your WeChat Work credentials
nano ~/wecom-adapter/.env

# 3. Start

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/deploy.sh (reported line 49)May include surrounding context.

sh
# 1. Deploy
bash <skill_dir>/scripts/deploy.sh

# 2. Edit .env with your WeChat Work credentials
nano ~/wecom-adapter/.env

# 3. Start

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/deploy.sh (reported line 60)May include surrounding context.

sh
# 1. Deploy
bash <skill_dir>/scripts/deploy.sh

# 2. Edit .env with your WeChat Work credentials
nano ~/wecom-adapter/.env

# 3. Start

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/security-guide.md (reported line 33)May include surrounding context.

md
### Token Caching

Access tokens cached with 5-minute safety margin to minimize API calls.

## Recommended Hardening

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/deploy.sh (reported line 35)May include surrounding context.

sh
fi

# Create .env template if not exists
if [ ! -f "$TARGET_DIR/.env" ]; then
  cat > "$TARGET_DIR/.env" << 'EOF'
# === WeChat Work Credentials ===
CORP_ID=your_corp_id

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/deploy.sh (reported line 36)May include surrounding context.

sh
fi

# Create .env template if not exists
if [ ! -f "$TARGET_DIR/.env" ]; then
  cat > "$TARGET_DIR/.env" << 'EOF'
# === WeChat Work Credentials ===
CORP_ID=your_corp_id

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
82% confidence
Finding

The skill declares no explicit tool scope or permissions despite clearly requiring access to environment variables for sensitive credentials. In an agent ecosystem, missing scope declarations weaken reviewability and allow broader-than-expected secret access, increasing the chance of accidental credential exposure or unsafe execution assumptions.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/security-guide.md (reported line 95)May include surrounding context.

md
## Environment Security

- Store `.env` with `chmod 600`
- Never commit `.env` to version control
- Rotate WEBHOOK_TOKEN periodically
- Monitor `logs/wecom-adapter.log` for anomalies

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The guide instructs users to expose a local webhook over a temporary public Cloudflare tunnel but does not explicitly warn that this creates an Internet-reachable endpoint handling sensitive enterprise messages. Even with token/signature checks, public exposure increases attack surface, can leak metadata, and may invite unsolicited probing or misconfiguration during setup.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

This shell script creates directories and copies or generates files in a user-supplied target path, which are safety-relevant filesystem modifications. Although it logs that deployment is happening, it does not give the user any chance to confirm or cancel before performing the writes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

Running npm install performs network access and may execute package lifecycle scripts, which can affect system state beyond simple file copying. The script does not disclose this specific action before executing it, aside from generic deployment messaging.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code persistently writes detailed request metadata and operational events to a local log file, including webhook parameters and downstream processing details. In a messaging bridge, these logs can expose sensitive identifiers, message data, and authentication-related values to local users, backups, or log collectors, expanding data retention beyond the stated integration purpose.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The webhook flow logs decrypted challenge data, CorpID, and later user message content, which directly captures confidential payloads after decryption. Because this service handles enterprise chat traffic, such logging increases the risk of privacy leakage, credential-adjacent data exposure, and unintended retention of regulated or internal business information.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill forwards inbound WeCom message content to an external OpenClaw service for AI processing without any in-code notice, consent mechanism, or filtering. In an enterprise messaging context, this can transmit sensitive employee or business data to another system, creating confidentiality, compliance, and data-governance risk if users or administrators are unaware of the data flow.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

User-visible strings, logs, and fallback responses are written exclusively in Chinese, including generated fallback text such as 抱歉,我还没学会回答这个。 and 服务暂时不可用,请稍后重试。. There is no indication that users can opt into another language or that the locale restriction is intentionally documented as region-specific.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/index.js:21