Back to skill

Security audit

WeChat Auto Reply (V26 Safe)

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real WeChat auto-reply tool, but it exposes chat data and automation controls through an unauthenticated network dashboard and uses unsafe shell-based automation.

Install only after reviewing the code and preferably after it is changed to bind to localhost, require authentication, remove shell=True command strings, sanitize dashboard rendering, and add explicit approval or a dry-run mode before sending messages. Do not expose the dashboard to a LAN/WAN or grant Accessibility and Screen Recording permissions on a machine with sensitive data unless you accept the risk.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (7)

T09 · Insecure Skill Coding Practices

Error
Location
dashboard.py:275
Finding

Unauthenticated Network Control Plane Enables Remote Command Execution

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
dashboard.py:258
Finding

Unauthenticated Disclosure of Private Chats, Logs, and Screenshots

Content
View full analysis
') def get_history(target): json_file = os.path.join( WORKSPACE, f"last_parsed_{target.replace(' ', '_')}.json" ) if os.path.exists(json_file): try: with open(json_file, 'r', encoding='utf-8') as f: data = json.load(f) return jsonify({ "history": data.get("accumulated_history", []) }) except: pass return jsonify({"history": []}) @app.route('/images/') def serve_image(filename): return send_from_directory(WORKSPACE, filename) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, debug=False) ``` ### Technical Analysis The status, history, and image routes do not verify the caller's identity or authorization. Because the application binds to `0.0.0.0`, these routes are available to other systems that can reach the host. The status response can reveal contact names, recent messages, generated replies, errors, logs, timestamps, and screenshot filenames. The history route returns persistent accumulated chat records, while the image route serves files from the workspace. The functionality of a local auto-reply service does not require unauthenticated network-wide access to raw chat histories and screenshots. This exposure exceeds least-privilege requirements. ### Attack Path 1. An at ...[truncated 906 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
dashboard.py:108
Finding

Stored Cross-Site Scripting in the Dashboard

Content
View full analysis
r.json()) .then(data => { const body = document.getElementById('modal-body'); body.innerHTML = ''; if (data.history && data.history.length > 0) { data.history.forEach(msg => { const isSelf = msg.startsWith('Self:'); const text = msg.replace( /^(Self:|Other:)\s*/, '' ); const cssClass = isSelf ? 'chat-bubble self' : 'chat-bubble'; body.innerHTML += `
${text}
` + `
`; }); } }); } ``` ```javascript for (const [target, info] of Object.entries(data.targets)) { let errorHtml = info.last_error ? `
⚠️ ${info.last_error}
` : ''; let chatHtml = '
'; if (info.last_messages && info.last_messages.length > 0) { info.last_messages.forEach(msg => { chatHtml += `
` + `${msg.replace('Other:', '')}
`; }); } if (info.last_reply) { chatHtml += `
${info.last_reply}
`; } grid.innerHTML += `
👤 ${target} ${errorHtml} ${chatHtml}
`; } ``` ```javascript data.global_logs.slice().reverse().forEach(log => { logs.innerHTML += `
` + ...[truncated 1678 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
monitor_main.py:49
Finding

Shell Injection in UI-Automation and Media Utilities

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
monitor_main.py:245
Finding

Indirect Prompt Injection Controls Automatically Executed Replies and Actions

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
monitor_main.py:200
Finding

Predictable Temporary Prompt Files Permit Symlink Attacks and Data Disclosure

Content
View full analysis
.txt` path. 3. The monitor opens the path for writing. 4. The operating system follows the attacker's symbolic link. 5. The monitor overwrites the linked destination with its privileges. 6. Alternatively, the attacker reads residual prompt files containing private conversation data if filesystem permissions permit. ### Impact Assessment The vulnerability may result in: - Overwriting files writable by the dashboard user. - Corrupting application configuration or user data. - Disclosur ...[truncated 284 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
requirements.txt:3
Finding

Unpinned Flask Dependency Creates Non-Reproducible Supply-Chain Risk

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (41)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · dashboard.py (reported line 269)May include surrounding context.

python
def get_daemon_status():
    global monitor_process
    # Double check via process list just in case
    check = subprocess.run("pgrep -f wechat-auto-reply/monitor_main.py", shell=True, capture_output=True)
    is_running = check.returncode == 0
    return jsonify({"running": is_running})

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
93% confidence
Finding

The unauthenticated start endpoint executes a destructive pkill command that forcibly terminates matching processes system-wide. Even though the command string is static, exposing this behavior over HTTP enables denial of service against local matching processes and makes the dashboard a process-kill primitive.

Content

Scanner excerpt · dashboard.py (reported line 282)May include surrounding context.

python
persona = "回复要简短、干脆,不带句号,用词口语化,像哥们一样聊天,语气轻松。"
    
    # Kill any existing instances
    os.system("pkill -9 -f wechat-auto-reply/monitor_main.py")
    
    script_path = os.path.expanduser("~/.openclaw/workspace/skills/wechat-auto-reply/monitor_main.py")
    cmd = ["python3", script_path, "--targets", targets, "--persona", persona, "--interval", "60"]

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · dashboard.py (reported line 287)May include surrounding context.

python
script_path = os.path.expanduser("~/.openclaw/workspace/skills/wechat-auto-reply/monitor_main.py")
    cmd = ["python3", script_path, "--targets", targets, "--persona", persona, "--interval", "60"]
    
    env = os.environ.copy()
    if apikey:
        env["GEMINI_API_KEY"] = apikey

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
94% confidence
Finding

The stop endpoint exposes an unauthenticated force-kill operation via HTTP, allowing any reachable client to terminate the monitor process. This creates a straightforward denial-of-service condition and can affect other matching processes because pkill uses a pattern match rather than a tracked PID.

Content

Scanner excerpt · dashboard.py (reported line 297)May include surrounding context.

python
@app.route('/api/stop', methods=['POST'])
def stop_daemon():
    global monitor_process
    os.system("pkill -9 -f wechat-auto-reply/monitor_main.py")
    if monitor_process:
        try:
            monitor_process.terminate()

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

This is a classic tool-parameter abuse issue: a generic command runner executes shell commands built from mutable inputs, and the rest of the file feeds it many attacker-influenceable values. In this skill, the dangerous context is amplified because those values come from chat metadata, temporary filenames, and model-generated content, making exploitation paths numerous.

Content

Scanner excerpt · monitor.py (reported line 16)May include surrounding context.

python
def run_cmd(cmd, timeout=120):
    try:
        return subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=timeout)
    except subprocess.TimeoutExpired:
        logger.error(f"Command timed out after {timeout}s: {cmd}")
        # Return a dummy completed process to avoid crashing the caller

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code actively focuses a WeChat window, injects clipboard contents, and sends messages via simulated keystrokes without per-message user approval. In a skill context, that enables unauthorized impersonation, accidental delivery to the wrong chat, and automated exfiltration or social-engineering actions if upstream inputs or model outputs are manipulated.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill captures screenshots of chat windows and submits their contents to external CLI tools for interpretation and reply generation. That exposes potentially sensitive conversation data to additional processing components and creates a privacy and data-leak risk, especially because the tool behavior, transport, and retention are not controlled in this file.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

This is a true tool-parameter-abuse risk because the code builds shell commands from values that can be influenced by runtime input, including target names used in filenames and shell substitutions. In a desktop automation skill with permissions to control UI, capture screens, and access the filesystem, command injection would give an attacker broad code-execution capability and amplify downstream harm.

Content

Scanner excerpt · monitor_main.py (reported line 51)May include surrounding context.

python
def run_cmd(cmd, timeout=120):
    try:
        return subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=timeout)
    except subprocess.TimeoutExpired:
        logger.error(f"Command timed out after {timeout}s: {cmd}")
        class DummyProcess:

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

This function pastes arbitrary generated text into the active WeChat UI and presses Enter with no confirmation step. In the context of an auto-reply agent, prompt injection, model mistakes, or misfocus on the wrong window can directly cause unauthorized messages or sensitive data disclosure to be sent to real contacts.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script sends conversation screenshots to an external summarization command, which may forward private message content to a local or remote model service. This creates a significant confidentiality risk because highly sensitive chat data is being processed outside WeChat without explicit disclosure, consent, or trust guarantees.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The prompt explicitly says not to send a URL for location requests, but the code converts the action into a generated map URL and sends it anyway. This creates a policy/implementation mismatch that can leak location information in a form the higher-level safety rule was meant to prevent, and undermines operator trust in the guardrail.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Generated replies are sent automatically to WeChat without user review. Because the reply content is derived from model output influenced by chat content and persona instructions, this can lead to accidental harassment, misinformation, privacy leaks, or compliance issues being sent under the user's identity.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

This is a true tool-parameter-abuse issue because the generic run_cmd wrapper accepts a full command string and executes it via the shell. In the context of this skill, user input flows into shell commands used for UI automation, making exploitation realistic and especially dangerous because successful injection would run with the local user's privileges on macOS.

Content

Scanner excerpt · send_location.py (reported line 10)May include surrounding context.

python
def run_cmd(cmd):
    try:
        res = subprocess.run(cmd, shell=True, capture_output=True, text=True, check=True)
        return res
    except subprocess.CalledProcessError as e:
        print(f"❌ Command failed: {cmd}\nError: {e.stderr}")

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · send_location.py (reported line 34)May include surrounding context.

python
print("🛡️ Safety Lock Check...")
    check_focus_cmd = "osascript -e 'tell application \"System Events\" to get name of first application process whose frontmost is true'"
    res = subprocess.run(check_focus_cmd, shell=True, capture_output=True, text=True)
    if "微信" not in res.stdout and "WeChat" not in res.stdout:
        print("🚨 SAFETY ABORT: WeChat is not the active window!")
        sys.exit(1)

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill exposes unrestricted shell execution and interpolates untrusted arguments into commands used to focus windows and set the clipboard. In an automation skill that sends content to a chat application, this is especially risky because attacker-controlled inputs can trigger arbitrary command execution in addition to unintended message delivery.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

This is a concrete instance of tool parameter abuse: a general-purpose shell execution primitive is exposed and then fed formatted command strings. Because the skill accepts external parameters and performs desktop automation, abuse of this primitive can lead to arbitrary system command execution and unauthorized actions on the user's workstation.

Content

Scanner excerpt · send_media.py (reported line 11)May include surrounding context.

python
logger = logging.getLogger(__name__)

def run_cmd(cmd):
    return subprocess.run(cmd, shell=True, capture_output=True, text=True)

def check_focus():
    res = run_cmd("osascript -e 'tell application \"System Events\" to get name of first application process whose frontmost is true'")

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill advertises a 'memory bank,' screenshot parsing, live snapshot preview, and historical chat viewing, but it does not clearly warn that chat history, screenshots, and derived data may be stored or displayed. In a messaging automation context, this omission is risky because users and affected contacts may be unaware that sensitive communications could persist locally or be exposed through the dashboard.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The documentation describes a tool requiring Screen Recording and Accessibility permissions and performing automated UI control, but it does not clearly warn users that this grants broad system-observation and input-injection capability. In this context, missing disclosure is dangerous because users may enable powerful permissions without understanding that the skill can read visible content and control other apps, increasing misuse and privacy risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The instructions explicitly mention access via the machine's LAN address (0.0.0.0) but do not warn that exposing the Flask dashboard beyond localhost can allow other hosts to reach a control panel that may start/stop automation and view sensitive chat artifacts. Given the dashboard's described capabilities, accidental network exposure materially increases the risk of unauthorized access, privacy loss, and misuse.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The safety statement is materially misleading because the skill does more than local visual OCR and keyboard/mouse simulation: it also runs a Flask dashboard, stores or serves screenshots/history, and manages API keys and subprocess state. Users may trust the '100% safe' and 'absolute no ban' language and underestimate the attack surface, privacy exposure, and operational risk introduced by the web interface and credential handling.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · dashboard.py (reported line 269)May include surrounding context.

python
def get_daemon_status():
    global monitor_process
    # Double check via process list just in case
    check = subprocess.run("pgrep -f wechat-auto-reply/monitor_main.py", shell=True, capture_output=True)
    is_running = check.returncode == 0
    return jsonify({"running": is_running})

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The endpoint accepts a credential-like value from the web UI and injects it into the child process environment as GEMINI_API_KEY. There is no warning in code-visible user messaging that the provided key will be transmitted to another process or used for external model access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code performs safety-impacting operations: it forcibly terminates existing monitor processes and starts a new background process using user-supplied targets and an API key. The endpoint has no confirmation step, no visible server-side warning/log about the kill/start action, and no inline comment or docstring disclosing the operational impact to users.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
91% confidence
Finding

This endpoint launches a background Python process based on HTTP requests without any authentication or CSRF protection. An attacker who can reach the dashboard can start arbitrary monitoring activity repeatedly, consume resources, and trigger downstream behavior in monitor_main.py using attacker-supplied parameters.

Content

Scanner excerpt · dashboard.py (reported line 291)May include surrounding context.

python
if apikey:
        env["GEMINI_API_KEY"] = apikey
    
    monitor_process = subprocess.Popen(cmd, env=env)
    return jsonify({"status": "started", "targets": targets})

@app.route('/api/stop', methods=['POST'])

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This endpoint triggers a destructive process-management action by issuing a forceful pkill and terminating the tracked subprocess, but it provides no confirmation prompt, warning message, or descriptive comment/docstring. Users invoking stop are not informed that the action forcibly kills matching processes rather than performing a graceful shutdown.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.