Back to skill

Security audit

微信消息文件发送skill

Security checks for vulnerabilities and agentic risk

Overview

This WeChat skill is purpose-built to send messages and files, but it uses stored WeChat credentials, lacks a clear confirmation gate, and can expose sensitive tokens or key material in logs.

Install only if you are comfortable giving the skill access to local OpenClaw WeChat account state and allowing it to send selected messages or files through WeChat. Review the recipient, message, and file path before invoking it, and avoid using it where execution logs may be visible to others because tokens and upload key material can be printed.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/main_send_msg.py:100
Finding

Sensitive WeChat Context Token Disclosed in Console Logs

Content
View full analysis

Vulnerability Details

File Location: scripts/main_send_msg.py:100
Vulnerability Type: Sensitive authentication material written to standard output
Risk Level: Medium

Vulnerable Code:

python
print(f"上下文Token: {CONTEXT_TOKEN if CONTEXT_TOKEN else '(为空,可能影响首次发送)'}")

Technical Analysis

The script reads a WeChat conversation context token from the OpenClaw account store and prints the complete value to standard output. This token is authentication-related session material and is not required in logs for the declared message-delivery functionality.

Standard output may be captured by OpenClaw execution logs, terminal recording, CI/CD systems, process supervisors, centralized logging services, or debugging transcripts. Consequently, principals that are not authorized to access the account configuration may nevertheless obtain the token through less-protected log storage.

Printing whether a context token is present would be sufficient for diagnostics. Printing its full value exceeds the minimum disclosure necessary to perform or troubleshoot message delivery.

Attack Path

  1. A legitimate user invokes main_send_msg.py to send a WeChat message.
  2. The script reads the context token from the account's .context-tokens.json file.
  3. Before sending the request, the script writes the complete token to standard output.
  4. An execution environment, process supervisor, or logging service stores the output.
  5. An attacker or lower-privileged operator with access to those logs retrieves the token.
  6. Depending on server-side token validation and binding, the exposed token may assist unauthorized interaction with or impersonation within the associated conversation.

Impact Assessment

The direct scope is the WeChat conversation associated with the exposed context token. Exploitation requires access to captured output or logs; this issue does not independently grant local code execution or system ...[truncated 378 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove the context token from all console and debug output.
  • Log only a boolean state, such as Context token present: yes.
  • If correlation is operationally necessary, use a short, non-reversible keyed fingerprint rather than any token substring.
  • Configure logging filters to redact fields named token, context_token, Authorization, and similar credential-bearing fields.
  • Review existing logs and delete or restrict any records containing previously exposed tokens.
  • Rotate affected context tokens where rotation is supported.
  • Add automated tests that fail if authentication values are passed to logging functions.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/main_send_msg.py:60
Finding

Configuration-Controlled API Endpoint Can Receive WeChat Credentials and Message Data

Content
View full analysis

Vulnerability Details

File Location: scripts/main_send_msg.py:60, scripts/main_send_msg.py:91-109, scripts/main_send_msg.py:143
Vulnerability Type: Missing destination validation for credential-bearing network requests
Risk Level: Medium

Vulnerable Code:

python
api_endpoint = f"{BASE_URL.rstrip('/')}/ilink/bot/sendmessage"
python
raw = json.dumps(payload, ensure_ascii=False)
headers = {
    "Content-Type": "application/json",
    "AuthorizationType": "ilink_bot_token",
    "Authorization": f"Bearer {BOT_TOKEN}",
    "X-WECHAT-UIN": x_wechat_uin,
    "Content-Length": str(len(raw.encode("utf-8"))),
}

response = requests.post(
    api_endpoint,
    headers=headers,
    data=json.dumps(payload, ensure_ascii=False).encode('utf-8'),
    timeout=15
)
python
BASE_URL = result[f"{account_id}"]["baseUrl"]

Technical Analysis

The text-message script obtains baseUrl from a local account configuration file and uses it without validating the URL scheme or destination hostname. The resulting request includes:

  • The WeChat bot bearer token in the Authorization header
  • The conversation context token in the JSON payload
  • The target user identifier
  • The complete message content
  • Request metadata associated with the account

If the account JSON is modified, replaced, or generated from an untrusted source, an attacker can direct this credential-bearing request to an arbitrary server. The implementation does not require HTTPS, enforce an official WeChat hostname allowlist, or explicitly prevent cross-origin redirects.

Network transmission is necessary for the Skill's declared messaging purpose. However, allowing a mutable configuration value to select any recipient of the credentials exceeds the minimum network privilege required. In contrast, the file-sending script uses fixed HTTPS WeChat hosts for its upload and send operations.

Attack Path

...[truncated 1401 chars]

Remediation
View remediation

Remediation Suggestions

  • Parse BASE_URL with a strict URL parser before use.
  • Require the https scheme.
  • Allowlist the exact official WeChat API hostname or a narrowly defined set of documented official hostnames.
  • Reject URLs containing user information, unexpected ports, fragments, or ambiguous hostname encodings.
  • Disable redirects for credential-bearing requests where possible:
    python
    requests.post(..., allow_redirects=False)
    
  • If redirects are operationally required, validate the scheme and hostname of every redirect target before forwarding credentials.
  • Verify restrictive ownership and permissions on the account directory and JSON files.
  • Consider ignoring configuration-provided origins entirely and using a trusted, fixed API origin.
  • Avoid including response bodies in logs unless they are redacted, because remote endpoints may return sensitive or attacker-controlled content.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/main_send_file.py:101
Finding

File Encryption Keys Generated with Non-Cryptographic Randomness and Partially Logged

Content
View full analysis

Vulnerability Details

File Location: scripts/main_send_file.py:101-102, scripts/main_send_file.py:133-137, scripts/main_send_file.py:333
Vulnerability Type: Weak cryptographic key generation and sensitive key-material logging
Risk Level: Medium

Vulnerable Code:

python
filekey = ''.join(random.choices('0123456789abcdef', k=32))
aeskey_hex = ''.join(random.choices('0123456789abcdef', k=32))
python
aes_key = bytes.fromhex(aes_key_hex)

with open(file_path, 'rb') as f:
    file_data = f.read()

cipher = AES.new(aes_key, AES.MODE_ECB)

padded_data = pad(file_data, AES.block_size, style='pkcs7')
encrypted_data = cipher.encrypt(padded_data)
python
print(f"准备成功,filekey: {prepare_result['filekey'][:16]}..., aeskey: {prepare_result['aeskey_hex'][:16]}...")

Technical Analysis

The script uses Python's random module to generate the AES key and file key. This module is based on a deterministic pseudo-random number generator and is not intended for cryptographic secrets. If its internal state can be inferred from other outputs or execution context, future values may become predictable.

The script also prints the first 16 hexadecimal characters of both generated values. For the AES key, this discloses 64 of its nominal 128 bits. Partial disclosure materially reduces the remaining search space and is unnecessary for file-upload diagnostics.

AES-ECB encrypts identical plaintext blocks into identical ciphertext blocks and provides no integrity or authenticity. This can reveal structural patterns in uploaded files. The audit recognizes that ECB and the encoded AES-key format may be required by the documented WeChat upload protocol; if so, changing the cipher mode unilaterally may break compatibility. Secure key generation and removal of key logging remain necessary regardless of protocol constraints.

The Base64 encoding of the AES key and transmission of encrypted content are ...[truncated 1769 chars]

Remediation
View remediation

Remediation Suggestions

  • Replace non-cryptographic key generation with the secrets module or os.urandom:
    python
    import secrets
    
    filekey = secrets.token_hex(16)
    aeskey_hex = secrets.token_hex(16)
    
  • Never print complete or partial encryption keys, file keys, upload parameters, bearer tokens, or context tokens.
  • Log only operation identifiers that cannot be used to derive or retrieve encrypted content.
  • Use an authenticated encryption mode such as AES-GCM if the upstream protocol supports it.
  • If AES-ECB is mandated by the WeChat protocol, document that compatibility constraint and compensate by using cryptographically secure random keys, TLS, strict key secrecy, short key lifetimes, and integrity checks supported by the protocol.
  • Use constant, vetted protocol implementations where available rather than maintaining custom cryptographic framing.
  • Add tests verifying that generated keys come from a cryptographically secure source and never appear in logs.
  • Restrict access to execution logs and rotate or invalidate upload material exposed by prior runs where supported.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (20)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

A second independently identified description-behavior mismatch indicates the skill claims account management, user info query, and broad file transmission support that are not actually evidenced, while local credential/token access is not transparently described. In a messaging skill, this kind of misrepresentation increases the chance of unintended data disclosure because reviewers may underestimate the sensitivity of the underlying file and network operations.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

A second independently identified description-behavior mismatch indicates the skill claims account management, user info query, and broad file transmission support that are not actually evidenced, while local credential/token access is not transparently described. In a messaging skill, this kind of misrepresentation increases the chance of unintended data disclosure because reviewers may underestimate the sensitivity of the underlying file and network operations.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill declares capabilities to read environment variables, access local files, and perform network operations, but does not declare any corresponding tool scope or permissions. This weakens reviewability and user consent because the skill can access local OpenClaw account/config data and transmit it externally without an explicit capability boundary.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger language for sending files is broad and ambiguous, making it easier for the agent to invoke transmission behavior from loosely related user requests. For a skill that can send local files externally, ambiguous invocation criteria increase the risk of accidental or over-broad data exfiltration.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill description does not clearly warn that it can actively send messages and local files to external recipients. Without a prominent user-facing warning, users may not understand that invoking the skill can cause external data transmission, especially when the skill also interacts with local account/config artifacts.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The automatic file-send conditions partially conflict with the requirement for explicit user intent: non-text messages with attachments may trigger sending behavior even when the user's goal is unclear. In a skill capable of transmitting files over WeChat, such ambiguity can cause unintended forwarding of user-provided or locally generated files to external recipients.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script reads local OpenClaw account state files and extracts bot tokens, user IDs, and context tokens from disk, giving it credential-access capability beyond simply sending a user-specified file. In a skill context, this is dangerous because it silently reaches into local state to obtain reusable secrets that could be abused for unauthorized messaging or later exfiltration.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/main_send_file.py (reported line 201)May include surrounding context.

python
}  
    
    # 发送POST请求
    resp = requests.post(
        "https://ilinkai.weixin.qq.com/ilink/bot/getuploadurl",
        headers=headers,
        data=  raw.encode('utf-8'),

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/main_send_file.py (reported line 484)May include surrounding context.

python
}  
    
    # 发送POST请求
    resp = requests.post(
        "https://ilinkai.weixin.qq.com/ilink/bot/getuploadurl",
        headers=headers,
        data=  raw.encode('utf-8'),

Tainted flow: 'cdn_url' from requests.post (line 242, network input) → httpx.post (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/main_send_file.py (reported line 250)May include surrounding context.

python
try:
        # 发送请求
        resp = httpx.post(
            cdn_url,
            headers=headers,
            content=encrypted_data,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill performs real file upload and message transmission to external WeChat services immediately once invoked, without any explicit confirmation step, dry-run mode, or clear disclosure of what recipient and file will be sent. In an agent environment, that raises the risk of unintended data disclosure or unreviewed outbound actions triggered by ambiguous or manipulated prompts.

Content

No source excerpt is available for this finding.

Tainted flow: 'headers' from requests.post (line 476, network input) → requests.post (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/main_send_file.py (reported line 484)May include surrounding context.

python
"Content-Length": str(len(raw.encode("utf-8"))),  
        }  
            # 发送POST请求
        response = requests.post(
            "https://ilinkai.weixin.qq.com/ilink/bot/sendmessage",
            headers=headers,
            data=  raw.encode('utf-8'),

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest claims the skill can send messages or files to specified WeChat contacts or groups, but main() hardcodes TARGET_USER_ID from the account's own stored userId and derives the context token from that same userId. There is no input path here for selecting another contact or group, so the implemented behavior is narrower than the declared capability.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script transmits a message using locally sourced account identifiers, context tokens, and bot credentials without any explicit user consent, warning, or trust boundary enforcement. In the context of an agent skill that can be invoked indirectly, this creates a risky capability for silent outbound actions and use of sensitive account state, especially because the skill is described as communication automation.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The manifest promises integrated account management, active delivery to specified WeChat contacts or groups, and transmission of multiple file types. In this file, the CLI accepts only an account ID and text message, derives TARGET_USER_ID from the local account JSON, and always constructs a text-only payload with item type 1; there is no caller-specified recipient selection, group targeting, or file/media sending logic.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script reads sensitive local OpenClaw account files to obtain bot tokens, base URL, user IDs, and context tokens, then uses them to perform authenticated messaging. In a skill environment, automatic access to credential-bearing local state is dangerous because a malicious or overly broad invocation could leverage stored secrets to act on the user's behalf without separate authentication or meaningful notice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The file contains user-facing docstrings and console messages in Chinese only, and the command-line usage examples also assume Chinese-language interaction. There is no indication that the user can choose another language or that the locale restriction is intentionally documented.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The code silently loads sensitive bot and context tokens from local account state files without notifying the user at the point of use. In a skill ecosystem, undisclosed access to local secrets increases the chance that users authorize behavior they do not realize includes credential harvesting from disk.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

The docstring says the main function gets an account ID and returns JSON, while the usage text shows a second argument named '' with examples like sending '你好'. In reality, the second argument is assigned to IMAGE_PATH and passed into the file-upload/send workflow, so the inline documentation contradicts the implemented behavior.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The docstring at L134 states the main function 'gets account ID from command-line arguments and returns JSON.' In reality, main parses arguments, loads account data, extracts credentials/tokens, and calls send_weixin_message(), which performs a network side effect and prints diagnostics rather than returning JSON.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.