Back to skill

Security audit

Wechat Sendmedia

Security checks for vulnerabilities and agentic risk

Overview

This skill is meant to send WeChat media, but it can turn arbitrary readable local file paths and sensitive troubleshooting data into chat-visible output without enough scoping or redaction.

Install only if you trust the WeChat channel users and the agent host environment. Before using it, restrict sends to a known workspace or upload directory, require confirmation for pre-existing local files, and avoid returning raw diagnostics or account-token path information to chat participants.

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
scripts/emit_media_reply.py:38
Finding

Unrestricted Local File Paths Can Be Transmitted to WeChat

Content
View full analysis
int: ap = argparse.ArgumentParser() ap.add_argument("file_path") ap.add_argument("--recipient", default="当前会话") ap.add_argument("--text", default="") ap.add_argument("--json-envelope", action="store_true", help="also emit legacy json envelope fields for debugging only") args = ap.parse_args() path = Path(args.file_path).expanduser().resolve() exists = path.exists() result = { "ok": exists, "file_path": str(path), "exists": exists, "recipient": args.recipient, } if not exists: result.update({ "error": "file_not_found", "message": f"file not found: {path}", }) print(json.dumps(result, ensure_ascii=False, indent=2)) return 1 media_type = guess_media_type(path) reply_text = render_reply_text(path, args.recipient, media_type, args.text) result.update({ "mediaType": media_type, "fileName": path.name, "mediaUrl": to_file_url(path), "reply_text": reply_text, "size": path.stat().st_size, }) ``` The documented workflow explicitly accepts arbitrary absolute paths and treats all non-image types as sendable files: ```markdown - Send a non-image file such as a PDF, text file, archive, or document. ... - `file_path`: absolute local path to an existing file, or a screenshot path produced earlier. ... 2. Ensure the target file exists. 3. Run `scripts/emit_media_reply.py` to validate the file and build the plain-text reply payload. 4. Return the script's `reply_text` value as the assistant message. ... Treat everything else as files. ``` ### Technical Analysis The helper resolves ...[truncated 2794 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/weixin_debug_send.js:17
Finding

Failure Diagnostics Expose Sensitive Runtime Data and Inspect Account Token Stores

Content
View full analysis
f.endsWith('.context-tokens.json')); for (const file of files) { const full = path.join(accountsDir, file); const data = readJsonIfExists(full); if (data && recipient && data[recipient]) { return { present: true, file: full }; } } return { present: false, file: null }; } catch { return { present: false, file: null }; } } ``` ```javascript function main() { const filePath = process.argv[2] || ''; const recipient = process.argv[3] || '当前会话'; const debugPath = process.argv[4] || ''; const accountsDir = path.join(process.env.HOME || '', '.openclaw/openclaw-weixin/accounts'); const debug = readJsonIfExists(debugPath) || {}; const uploadUrl = debug.upload_url || debug.uploadfullurl || 'n/a'; let uploadUrlHost = 'n/a'; try { if (uploadUrl !== 'n/a') uploadUrlHost = new URL(uploadUrl).host; } catch {} const encrypted = debug.encrypted_param || debug.downloadEncryptedQueryParam || ''; const sendResp = debug.sendmessage_response || debug.sendmessage_raw || 'n/a'; const sendStatus = debug.sendmessage_status || 'n/a'; const context = findContextToken(accountsDir, recipient === '当前会话' ? '' : recipient); const exists = !!(filePath && fs.existsSync(filePath)); const mediaType = guessMediaType(filePath); let probableCause = '需要检查宿主是否把结构化 media 回复映射到了 openclaw-weixin 的 sendMedia 路径'; if (!exists) probableCause = '文件路径不存在或截图文件尚未生成'; else if (!context.present && recipient !== '当前会话') probableCause = '未找到该接收 ...[truncated 4297 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill is presented as a media-sending helper, but its documented workflow also includes diagnostic behavior that reads status artifacts, scans local account directories, and reports internal runtime state. That mismatch can lead operators and users to authorize a seemingly simple messaging skill that actually inspects local application state and exposes sensitive debugging information.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill describes behavior that relies on scripts performing validation and debugging with access to environment, filesystem state, and likely network-adjacent runtime behavior, but it declares no explicit tool scope or permissions. In a skill system, missing scope boundaries increases the risk of overbroad execution and makes it harder for the host to constrain file, env, or network access to only what is required.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The output contract explicitly includes absolute local file paths, raw send responses, upload URL details, and context-token presence in user-visible text. This can leak sensitive system layout, operational metadata, and potentially useful reconnaissance information to an end user or chat participant who does not need backend diagnostics.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The instruction 'Summarize the result in Chinese' forces a specific language for responses. The file does not offer user opt-in or explain a necessary locale restriction, which conflicts with the language/locale policy criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The user-facing reply text uses fixed Chinese strings such as "图片", "文件", and "发送成功". This enforces a specific language in the skill output with no user opt-in or locale selection, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The legacy envelope text is emitted as either "这是你要的图片" or "这是你要的文件", again hard-coding Chinese for user-visible content. No alternative locale, opt-in, or justification is provided in the file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The default value "当前会话" is user-facing output data and assumes Chinese as the interaction language. Because the file provides no language selection or documented locale constraint, this is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.