Back to skill

Security audit

macos-wechat-send

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real WeChat automation skill, but it needs Review because it can send real messages and files without a confirmation boundary and has a concrete file-path AppleScript injection risk.

Only install after reviewing it carefully. It will control your Mac UI, overwrite clipboard contents, and send messages or files from your logged-in WeChat account. Confirm the recipient and content yourself before running it, avoid sensitive files, and do not use unusual or untrusted file paths until the AppleScript path handling and recipient verification are fixed.

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
wechat-send.py:50
Finding

AppleScript Injection Through Crafted File Paths

Content
View full analysis

Vulnerability Details

File Location: wechat-send.py, lines 50–64
Vulnerability Type: AppleScript injection leading to arbitrary command execution
Risk Level: High

python
def copy_file_in_finder(file_path):
    """在 Finder 中选中文件并复制(Cmd+C)"""
    abs_path = os.path.abspath(file_path)
    
    # 使用 POSIX file 语法,更好地处理特殊字符
    script = f'''
    tell application "Finder"
        activate
        select POSIX file "{abs_path}"
        delay 0.3
        tell application "System Events"
            keystroke "c" using command down
        end tell
        delay 0.3
    end tell
    '''
    
    try:
        subprocess.run(['osascript', '-e', script], check=True, timeout=10)

Technical Analysis

The file path is interpolated directly into executable AppleScript source without escaping quotation marks, backslashes, or newline characters. macOS filenames can contain characters capable of terminating the AppleScript string literal.

Although subprocess.run() uses an argument array and therefore avoids shell parsing at the Python process boundary, this does not prevent injection into the AppleScript language itself. A crafted existing filename can close the POSIX file string and append additional AppleScript statements. AppleScript supports commands such as do shell script, so successful injection can result in arbitrary local command execution.

The preceding is_file_path() validation only confirms that the supplied value refers to an existing file. It does not make the filename safe for inclusion in AppleScript source.

Attack Path

  1. An attacker creates, supplies, or persuades the user to create a file whose name contains AppleScript syntax, including a string terminator and injected statement.
  2. The user invokes the Skill with the crafted file path as an item to send.
  3. is_file_path() accepts the argument because the crafted path identifies an existing file.

...[truncated 796 chars]

Remediation
View remediation

Remediation Suggestions

Do not concatenate file paths into AppleScript source. Pass the path as a separate osascript argument and retrieve it through an on run argv handler so that it remains data:

python
script = '''
on run argv
    set targetPath to item 1 of argv
    tell application "Finder"
        activate
        select POSIX file targetPath
        delay 0.3
        tell application "System Events"
            keystroke "c" using command down
        end tell
        delay 0.3
    end tell
end run
'''

subprocess.run(
    ['osascript', '-e', script, '--', abs_path],
    check=True,
    timeout=10
)

Additional hardening should include:

  • Resolve and validate the path before invoking AppleScript.
  • Reject unsupported file types or locations if the operational requirements permit allowlisting.
  • Avoid implementing manual escaping when a parameterized argument channel is available.
  • Add regression tests using filenames containing double quotes, backslashes, Unicode characters, and newline characters.
  • Report AppleScript failures clearly rather than continuing with uncertain clipboard or UI state.

T09 · Insecure Skill Coding Practices

Warning
Location
wechat-send.py:162
Finding

Unverified Search Result Can Send Messages or Files to the Wrong Recipient

Content
View full analysis

Vulnerability Details

File Location: wechat-send.py, lines 162–181; equivalent logic is repeated at lines 292–311
Vulnerability Type: Missing recipient identity verification in sensitive UI automation
Risk Level: Medium

python
        search_script = '''
        tell application "System Events"
            tell process "WeChat"
                -- 先按 ESC 清除任何打开的窗口或搜索框
                key code 53
                delay 0.2
                
                -- 按 Cmd+A 全选清空搜索框
                keystroke "a" using command down
                delay 0.2
                
                -- 按 Cmd+F 重新搜索
                keystroke "f" using command down
                delay 0.3
                
                -- 粘贴联系人名字
                keystroke "v" using command down
                delay 0.5
                
                -- 按回车选择第一个搜索结果
                keystroke return
                delay 0.5
            end tell
        end tell
        '''

After selecting the first result, the message path immediately pastes and sends content:

python
    send_script = '''
    tell application "System Events"
        tell process "WeChat"
            -- 等待一下确保输入框已聚焦
            delay 0.3
            
            -- 粘贴消息内容
            keystroke "v" using command down
            delay 0.3
            
            -- 按回车发送
            keystroke return
        end tell
    end tell
    '''

Technical Analysis

The automation searches for the supplied contact name and unconditionally presses Enter to choose the first result. It does not inspect the search results, verify an exact match, detect ambiguous contacts, or confirm the title of the conversation opened after selection.

Fixed delays do not establish that the interface reached the expected state. Search result ordering, delayed rendering, partial matches, duplicate display names, stale focus ...[truncated 1386 chars]

Remediation
View remediation

Remediation Suggestions

Replace blind first-result selection with verified recipient selection:

  • Query WeChat's Accessibility hierarchy for matching search results.
  • Require an exact normalized match against the requested contact name.
  • Abort if there are zero matches or multiple indistinguishable matches.
  • After opening the conversation, read its displayed title through the Accessibility API and compare it with the intended recipient.
  • Do not paste or send content unless recipient verification succeeds.
  • Require explicit user confirmation before sending files or sensitive content when recipient identity cannot be uniquely established.
  • Replace fixed delays with bounded waits that test for specific UI states.
  • Store a stable contact identifier if WeChat exposes one; do not treat a persisted display name as proof that the correct conversation is active.
  • Apply the corrected workflow to both the message and file sending functions to avoid divergent security behavior.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (18)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The description presents automatic message and file sending as a normal capability but does not prominently warn that it can perform irreversible external actions using the user's logged-in WeChat account. In an agent setting, lack of a clear warning increases the chance that users or orchestrators underestimate the sensitivity of the skill and permit high-impact actions without informed consent.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger conditions are broad enough that an agent could invoke this skill whenever a user mentions sending a WeChat message or automating WeChat, without a strong confirmation boundary. Because the skill performs real GUI automation that can send messages and files to external recipients, accidental invocation could cause unintended disclosure, spam, or actions taken under the user's identity.

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 · wechat-send.py (reported line 40)May include surrounding context.

python
def set_clipboard(text):
    """设置剪贴板内容 - 直接用 Python 设置,避免转义问题"""
    # 使用 macOS 的 pbcopy 命令,通过 stdin 传递内容
    proc = subprocess.Popen(['pbcopy'], stdin=subprocess.PIPE, text=True)
    proc.stdin.write(text)
    proc.stdin.close()
    proc.wait()

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
88% confidence
Finding

This call passes an AppleScript string containing unescaped user-controlled file path data into osascript. A crafted path containing quotes or AppleScript metacharacters can break out of the intended string literal and alter the script's behavior, potentially causing unintended UI actions or AppleScript execution in the user's desktop session.

Content

Scanner excerpt · wechat-send.py (reported line 67)May include surrounding context.

python
'''
    
    try:
        subprocess.run(['osascript', '-e', script], check=True, timeout=10)
        return True
    except Exception as e:
        print(f"✗ 复制文件失败:{e}")

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 · wechat-send.py (reported line 79)May include surrounding context.

python
# 方式 1:用 open 命令打开/激活应用
    try:
        subprocess.run(['open', '-a', 'WeChat'], check=True, timeout=5)
        time.sleep(0.3)
    except:
        pass

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 · wechat-send.py (reported line 86)May include surrounding context.

python
# 方式 2:用 AppleScript activate
    try:
        subprocess.run(['osascript', '-e', 'tell application "WeChat" to activate'], check=True, timeout=5)
        time.sleep(0.3)
    except:
        pass

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 · wechat-send.py (reported line 93)May include surrounding context.

python
# 方式 3:用 System Events 设置前台
    try:
        subprocess.run(['osascript', '-e', 'tell application "System Events" to set frontmost of process "WeChat" to true'], check=True, timeout=5)
        time.sleep(0.3)
    except:
        pass

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 · wechat-send.py (reported line 108)May include surrounding context.

python
end tell
        end tell
        '''
        subprocess.run(['osascript', '-e', script], check=True, timeout=5)
        time.sleep(0.3)
    except:
        pass

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 · wechat-send.py (reported line 166)May include surrounding context.

python
'''
            
            try:
                subprocess.run(['osascript', '-e', dummy_script], check=True, timeout=10)
            except Exception as e:
                print(f"✗ 垫脚石失败:{e}")
                return False

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 · wechat-send.py (reported line 299)May include surrounding context.

python
'''
            
            try:
                subprocess.run(['osascript', '-e', dummy_script], check=True, timeout=10)
            except Exception as e:
                print(f"✗ 垫脚石失败:{e}")
                return False

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 · wechat-send.py (reported line 201)May include surrounding context.

python
'''
        
        try:
            subprocess.run(['osascript', '-e', search_script], check=True, timeout=10)
        except Exception as e:
            print(f"✗ 搜索联系人失败:{e}")
            return False

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 · wechat-send.py (reported line 334)May include surrounding context.

python
'''
        
        try:
            subprocess.run(['osascript', '-e', search_script], check=True, timeout=10)
        except Exception as e:
            print(f"✗ 搜索联系人失败:{e}")
            return False

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 · wechat-send.py (reported line 231)May include surrounding context.

python
'''
    
    try:
        subprocess.run(['osascript', '-e', send_script], check=True, timeout=10)
        if is_first:
            print(f"✓ 消息已发送给:{contact_name}")
            # 保存当前联系人为上一次发送的联系人

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 · wechat-send.py (reported line 374)May include surrounding context.

python
'''
    
    try:
        subprocess.run(['osascript', '-e', send_script], check=True, timeout=15)
        if is_first:
            print(f"✓ 文件已发送给:{contact_name}")
            save_last_contact(contact_name)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

This shell script performs an external messaging action by invoking wechat-send.py with user-supplied content, which is effectively a network/outbound communication operation. While the usage text explains how to invoke the command, it does not warn the user that message content will be transmitted to an external service or contact, and there is no confirmation prompt before sending.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The top-level documentation describes the script as an automation tool using AppleScript and clipboard copy/paste for sending WeChat messages and files. However, the implementation also stores contact state in ~/.openclaw/workspace/skills/wechat-send/.last_contact, which is a behavioral side effect not reflected in the documented intent and could affect privacy expectations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

This Python file contains natural-language docstrings and CLI output entirely in Chinese, including the usage/help text later in the file. Under the policy rule, forcing a specific language without user opt-in is a locale/language policy violation unless the constraint is explicitly documented and justified, which is not present here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script's comments and especially its user-visible echo output are written only in Chinese, with no option to select another language or locale. This can violate language/locale policy when a skill imposes a language on users without documented opt-in or justification.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.