Back to skill

Security audit

WeChat Video Downloader

Security checks for vulnerabilities and agentic risk

Overview

This skill appears intended to download WeChat article videos, but its URL and output-file handling are too broad for that purpose.

Review this before installing if you expect strict WeChat-only behavior. Use it only with trusted mp.weixin.qq.com article links, avoid passing absolute or traversal output paths, and prefer a patched version that restricts allowed hosts, blocks private-network targets and redirects, confines downloads to a dedicated folder, and refuses overwrites by default.

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/download_wechat_video.py:95
Finding
Unrestricted URL Handling Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `scripts/download_wechat_video.py:95` and `scripts/download_wechat_video.py:64-77` **Vulnerability Type**: Unrestricted URL access / server-side request forgery **Risk Level**: High ### Vulnerable Code The supplied article URL is opened without validating its scheme, hostname, resolved IP address, or redirect destination: ```python result = run_browser_command("open", {"targetUrl": article_url}) ``` The video URL extracted from that page is subsequently passed directly to `curl`: ```python cmd = [ "curl", "-L", "-o", output_path, "-H", f"User-Agent: {user_agent}", "-H", f"Referer: {referer}", "-H", "Accept: video/webm,video/ogg,video/mp4,application/octet-stream", "--progress-bar", video_url ] print(f"开始下载视频到:{output_path}") result = subprocess.run(cmd) ``` ### Technical Analysis The skill documentation presents the input as a WeChat article URL, but the implementation does not enforce that boundary. Any caller-provided URL is forwarded to the OpenClaw browser. The extracted video source is also trusted without validating its origin before it is passed to `curl`. Because `curl` uses `-L`, redirects are followed without checking whether the final destination remains on an approved WeChat or Tencent host. The implementation also does not prohibit loopback, private, link-local, or other internal network addresses. Argument-array subprocess execution prevents shell metacharacter injection, but it does not prevent URL-based request forgery. An attacker-controlled page can expose a crafted video source referring to a network destination accessible from the machine running the skill. ### Attack Path 1. An attacker causes the skill to receive a URL outside the intended `mp.weixin.qq.com` scope. 2. The script passes the URL to `openclaw browser open` without validation. 3. The attacker-controlled page presents a matching video playback button. 4. After the script clicks the butt ...[truncated 951 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse the article URL with `urllib.parse.urlsplit` and require: - The `https` scheme. - No embedded username or password. - An exact approved hostname, such as `mp.weixin.qq.com`. - A valid, expected port. 2. Resolve the hostname and reject loopback, private, link-local, reserved, multicast, and unspecified addresses using Python's `ipaddress` module. 3. Validate every redirect destination rather than relying on unrestricted `curl -L` behavior. 4. Apply equivalent validation to the extracted video URL. Allow only explicitly approved HTTPS video hosts, such as the required WeChat or Tencent media domains. 5. Restrict curl protocols, for example with `--proto =https` and `--proto-redir =https`. 6. Consider performing the download through application code with explicit redirect callbacks so each redirect target can be revalidated. 7. Apply network-level egress controls to prevent the process from reaching loopback, private networks, and cloud metadata services where those destinations are unnecessary. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/download_wechat_video.py:168
Finding
Caller-Controlled Output Path Allows Arbitrary Writable-File Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `scripts/download_wechat_video.py:168-176` and `scripts/download_wechat_video.py:195-197` **Vulnerability Type**: Unrestricted file path and unsafe file overwrite **Risk Level**: Medium ### Vulnerable Code The output filename is accepted directly from the command line, resolved to an absolute path, and supplied to the download operation: ```python if not output_filename: vid = video_url.split("vid=")[-1].split("&")[0] if "vid=" in video_url else "wechat_video" output_filename = f"{vid}.mp4" output_path = Path(output_filename).resolve() # 6. 下载视频 success = download_video(video_url, str(output_path)) ``` The command-line value is not constrained before use: ```python article_url = sys.argv[1] output_filename = sys.argv[2] if len(sys.argv) > 2 else None success = download_wechat_video(article_url, output_filename) ``` The destination is ultimately passed to `curl -o`, which can replace an existing writable file: ```python cmd = [ "curl", "-L", "-o", output_path, "-H", f"User-Agent: {user_agent}", "-H", f"Referer: {referer}", "-H", "Accept: video/webm,video/ogg,video/mp4,application/octet-stream", "--progress-bar", video_url ] ``` ### Technical Analysis `Path.resolve()` normalizes a path but does not make it safe. Absolute paths and traversal paths can resolve outside the intended working directory. The script neither confines output to a dedicated download directory nor rejects existing files or symbolic-link destinations. When the resulting path is passed to `curl -o`, an existing file writable by the process may be truncated and replaced with downloaded content. The script runs with the invoking user's permissions, so the affected scope includes files writable by that user or service account. This is not shell command injection because `subprocess.run` receives an argument list. The security issue is unrestricted filesystem destination selection. ### Attack Pa ...[truncated 1097 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create a dedicated download directory with restrictive permissions. 2. Treat the caller-provided value as a filename only: - Reject absolute paths. - Reject `..` path components. - Reduce the value to a validated basename. - Permit only a conservative character set and expected extension. 3. Resolve both the destination directory and candidate file, then verify that the candidate remains inside the approved directory with `Path.is_relative_to()` or an equivalent containment check. 4. Reject symbolic links and inspect every relevant path component before writing. 5. Refuse to overwrite existing files by default. Generate a unique name or require explicit trusted confirmation. 6. Create the destination atomically with exclusive semantics, such as `os.open` using `O_CREAT | O_EXCL | O_NOFOLLOW`, and download through the resulting file descriptor where practical. 7. Download to a securely created temporary file inside the approved directory, validate the content type and size, and atomically rename it to the final non-existing destination. 8. Run the skill under a minimally privileged account with access only to its designated download directory. ]]>
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (5)

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The entire skill description is written in Chinese, including operational instructions and warnings, with no indication that other languages are supported or that Chinese is a required locale for compliance or regional scope. Under the policy for natural-language violations, forcing a specific language without user opt-in is a reportable issue.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill invokes shell commands and a local Python script but declares no explicit tool scope or permission boundaries. In an agent environment, this can enable broader-than-expected command execution, making accidental or unsafe invocation easier and reducing auditability of what the skill is allowed to do.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The trigger phrase includes the very broad term '下载视频', which can match many unrelated user requests and cause this skill to activate unexpectedly. Because the skill performs shell execution and downloads remote content, mis-triggering increases the chance of unintended network access, file writes, or use on non-WeChat URLs if routing is imperfect.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
else:
                cmd.append(f"--{key}={value}")
    
    result = subprocess.run(cmd, capture_output=True, text=True)
    if result.returncode != 0:
        print(f"浏览器命令失败:{result.stderr}")
        return None
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
]
    
    print(f"开始下载视频到:{output_path}")
    result = subprocess.run(cmd)
    
    if result.returncode == 0:
        file_size = os.path.getsize(output_path)
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Static analysis

No suspicious patterns detected.