Back to skill

Security audit

WeChat Sender by dxx

Security checks for vulnerabilities and agentic risk

Overview

The skill is meant to send WeChat messages, but its actual sender does not enforce the promised user authorization, contact allowlist, or meaningful rate limits.

Review this skill before installing. It should only be used where you trust the agent and the local OpenClaw Gateway to enforce consent, recipient restrictions, and rate limits, because the packaged sender script does not enforce those protections itself. Avoid using file sending until authorization, allowlisting, path review, and quota controls are fixed in the actual send path.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/send_message.py:48
Finding

Documented Authorization and Recipient Restrictions Are Not Enforced

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/send_message.py:23
Finding

Process-Local Delay Does Not Enforce Documented Messaging Quotas

Content
View full analysis
0: elapsed = current_time - _last_send_time if elapsed < RATE_LIMIT["cooldown_seconds"]: wait_time = RATE_LIMIT["cooldown_seconds"] - elapsed print(f"[等待] 频率限制,等待 {wait_time:.1f} 秒...") time.sleep(wait_time) _last_send_time = time.time() ``` ### Technical Analysis The implementation declares `max_per_minute`, but it never records a window of send timestamps or compares a count against that value. The only active control is a three-second delay based on `_last_send_time`. That timestamp is a module-level in-memory variable. The documented command-line usage starts a new Python process for each invocation, so `_last_send_time` is initialized to zero every time. Parallel processes also maintain independent values. Consequently, separate invocations can bypass even the three-second delay. The reference documentation additionally claims daily, burst, per-minute, and stricter group limits. Those limits do not exist in the executable implementation. The timestamp is also updated before the HTTP request succeeds, meaning it does not provide reliable accounting of successful delivery. ### Attack Path 1. An attacker or automated workflow launches many independent sender processes: ```bash for i in $(seq 1 100); do python3 scripts/send_message.py --to "Target" --text "Message $i" & done wait ``` 2. Every process initializes `_last_send_time` to zero. 3. Each first call to `check_rate_limit()` proceeds without sleeping. 4. The configured `max_per_minut ...[truncated 958 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (8)

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · references/wechat-api.md (reported line 103)May include surrounding context.

发送文字消息

bash
curl -X POST http://127.0.0.1:18789/api/wechat/send \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "openclaw-weixin",

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
90% confidence
Finding

The request_auth() API includes an auto_confirm path that directly grants authorization without interactive user consent. In an agent skill whose purpose is to ensure explicit approval before sending messages, this bypass can be invoked by surrounding code or misconfiguration to silently authorize sensitive actions, defeating the consent control entirely.

Content

Scanner excerpt · scripts/auth_helper.py (reported line 112)May include surrounding context.

python
return False


def request_auth(operation, auto_confirm=False):
    """
    请求用户授权

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · scripts/auth_helper.py (reported line 118)May include surrounding context.

python
Args:
        operation: 操作描述
        auto_confirm: 是否自动确认(仅用于测试)
    
    Returns:
        bool: 是否获得授权

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
95% confidence
Finding

This line is the concrete branch where auto_confirm causes grant_auth(operation) to execute immediately and returns success. Because the skill context involves authorization for sending WeChat messages, including potentially dangerous bulk or automated sending, this bypass materially increases the risk of unauthorized messaging or spam if reachable by the agent or wrapper code.

Content

Scanner excerpt · scripts/auth_helper.py (reported line 123)May include surrounding context.

python
Returns:
        bool: 是否获得授权
    """
    if auto_confirm:
        grant_auth(operation)
        return True

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The helper stores a caller-supplied authorization duration in grant_auth(), but all authorization checks and status reporting use the fixed AUTH_VALIDITY constant instead of the stored value. This creates a security-policy mismatch: operators may believe consent duration is constrained or extended as configured, while the enforcement logic always grants up to one hour of access, which can allow actions outside the intended approval window.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

该文档标题及全文内容均固定使用中文,没有提供可选语言、双语说明或适用范围说明。若组织要求技能文档避免在无用户选择的情况下强制特定语言,这属于自然语言层面的语言策略问题。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code file contains natural-language documentation and command help entirely in Chinese, starting with the module docstring and continuing throughout the user-facing interface. Under the policy, forcing a specific language without offering the user a language or locale choice is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/test_sender.py (reported line 194)May include surrounding context.

python
if method_name.startswith('test_'):
                total += 1
                try:
                    getattr(instance, method_name)()
                    passed += 1
                    print(f"  ✅ {method_name}")
                except Exception as e:

Static analysis

No suspicious patterns detected.