Back to skill

Security audit

Web to WeChat

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly matches its WeChat drafting purpose, but it has review-worthy risks around account-changing publishing, unsafe command templates, arbitrary URL fetching, and automatic dependency installation.

Review this skill before installing. Use it only in an isolated environment, pin and preinstall dependencies, audit the companion WeChat skills, avoid scraping internal/private URLs, and require an explicit final approval before any WeChat draft is created. Do not paste WeChat AppSecret values into generated command strings or logs.

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

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/scrape_web.py:127
Finding
Unrestricted URL Fetching Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `scripts/scrape_web.py`, lines 127–144 **Vulnerability Type**: Server-Side Request Forgery through an unrestricted user-controlled URL **Risk Level**: High ### Vulnerable Code ```python def fetch_page(url: str, timeout: int = 30) -> tuple: """Fetch page HTML and return (html_text, response).""" print(f"[FETCH] Fetching: {url}") try: resp = requests.get(url, headers=HEADERS, timeout=timeout, allow_redirects=True) resp.raise_for_status() # Detect encoding if resp.encoding and resp.encoding.lower() == "iso-8859-1": resp.encoding = resp.apparent_encoding html = resp.text print(f"[OK] Fetched {len(html)} bytes, encoding: {resp.encoding}") return html, resp except requests.exceptions.Timeout: print(f"[ERROR] Request timed out after {timeout}s") return "", None except requests.exceptions.HTTPError as e: print(f"[ERROR] HTTP error: {e}") return "", None except Exception as e: print(f"[ERROR] Fetch failed: {e}") return "", None ``` ### Technical Analysis The required `--url` argument is passed directly to `requests.get()` without validating its scheme, hostname, resolved IP address, or destination network. Redirects are explicitly enabled through `allow_redirects=True`, and redirect destinations are not revalidated. As a result, a user can make the host running the Skill send requests to network locations that may not be directly accessible to that user. Potential targets include: - Loopback services such as `127.0.0.1` and `::1` - Private IPv4 and IPv6 networks - Link-local services - Cloud instance metadata endpoints - Internal administration panels and APIs - Public URLs that redirect to an internal destination The scraper subsequently extracts response content and writes it to Markdown or JSON. The workflow may then expose that content to the agent or publish it to a We ...[truncated 1168 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Accept only explicitly supported `http` and `https` schemes. 2. Resolve the hostname before connecting and reject every address classified as loopback, private, link-local, multicast, unspecified, reserved, or otherwise non-global. 3. Disable automatic redirects and validate each redirect target before following it. 4. Repeat DNS and IP validation immediately before each connection to reduce DNS-rebinding risk. 5. Route scraping through an isolated outbound proxy that enforces destination restrictions. 6. Consider maintaining an allowlist of supported public domains where operationally practical. 7. Apply response-size and content-type limits to reduce denial-of-service exposure. 8. Keep the scraper in a sandbox without access to internal management networks or cloud metadata endpoints. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:212
Finding
Untrusted Article Metadata Can Be Injected into an Executable Python Command<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 212–227 **Vulnerability Type**: Code injection and sensitive credential exposure through unsafe command construction **Risk Level**: High ### Vulnerable Code ```python python -c " import os, subprocess, sys os.environ['WECHAT_APP_ID'] = '<app_id>' os.environ['WECHAT_APP_SECRET'] = '<app_secret>' result = subprocess.run([ sys.executable, r'<anything-to-wechat_skill_dir>/scripts/publish_to_wechat.py', '--file', r'<workspace>/wechat_article.html', '--title', '<article_title>', '--cover', r'<workspace>/wechat_cover_compressed.jpg', '--digest', '<article_summary_under_120_chars>', '--source-url', '<original_url>' ], capture_output=True, text=True, encoding='utf-8') print(result.stdout) print(result.stderr) " ``` ### Technical Analysis The Skill instructs the agent to substitute credentials, paths, article metadata, and the source URL directly into Python source passed through `python -c`. The article title, summary, and original URL can originate from an untrusted webpage or user input. A value containing a single quote and valid Python syntax can terminate one of the quoted string literals and inject additional Python statements. Shell metacharacters may also interact with the outer command string, depending on the shell used to execute the generated command. Although `subprocess.run()` itself uses an argument list, that protection occurs only after the dynamically assembled `python -c` source has already been interpreted. It therefore does not prevent injection into the surrounding Python program. The template also embeds `WECHAT_APP_SECRET` directly into command-line source. Command arguments may be visible in process inspection interfaces, diagnostic output, terminal history, execution logs, or monitoring systems. ### Attack Path 1. An attacker controls or influences a webpage title, digest, source URL, or other substituted metadata. 2. The Skill scrapes t ...[truncated 1091 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `python -c` publishing template. 2. Invoke `publish_to_wechat.py` from trusted wrapper code using a fixed subprocess argument array. 3. Pass article metadata only as argument values, never as generated Python or shell source. 4. Avoid shell execution and do not use `shell=True`. 5. Inherit `WECHAT_APP_ID` and `WECHAT_APP_SECRET` from a preconfigured environment or retrieve them through an approved secret manager. 6. Never embed secrets into command strings, generated source code, logs, or documentation examples intended for direct interpolation. 7. Validate metadata lengths and reject control characters, while retaining structured argument passing as the primary defense. 8. Treat every scraped title, author, digest, URL, and HTML fragment as attacker-controlled. 9. Run the publisher with a minimally privileged account and credentials limited to the required WeChat account operations. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/scrape_web.py:32
Finding
Runtime Installation of Unpinned Dependencies Creates Supply-Chain Exposure<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/scrape_web.py`, lines 32–53 - `scripts/compress_image.py`, lines 29–34 - `README.md`, lines 16–26 - `SKILL.md`, lines 46–58 **Vulnerability Type**: Unpinned dependency installation and runtime execution of externally supplied packages **Risk Level**: Medium ### Vulnerable Code From `scripts/scrape_web.py`: ```python try: import requests except ImportError: print("[INFO] Installing requests...") import subprocess subprocess.check_call([sys.executable, "-m", "pip", "install", "requests", "-q"]) import requests try: from bs4 import BeautifulSoup except ImportError: print("[INFO] Installing beautifulsoup4...") import subprocess subprocess.check_call([sys.executable, "-m", "pip", "install", "beautifulsoup4", "-q"]) from bs4 import BeautifulSoup try: import html2text except ImportError: print("[INFO] Installing html2text...") import subprocess subprocess.check_call([sys.executable, "-m", "pip", "install", "html2text", "-q"]) import html2text ``` From `scripts/compress_image.py`: ```python try: from PIL import Image except ImportError: print("[INFO] Installing Pillow...") import subprocess subprocess.check_call([sys.executable, "-m", "pip", "install", "Pillow", "-q"]) from PIL import Image ``` The setup instructions also install unpinned packages and companion Skills: ```bash python -m pip install requests beautifulsoup4 html2text markdown Pillow ``` ```bash clawhub install anything-to-wechat clawhub install file-to-wechat ``` ### Technical Analysis The scripts automatically invoke `pip` when an import is unavailable. No exact versions, package hashes, lockfiles, trusted index configuration, or artifact verification are used. Package installation can execute package build and installation logic. Importing the newly installed package then executes its initialization code. Consequently, the effective code run by th ...[truncated 1484 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove all automatic `pip install` behavior from runtime scripts. 2. Fail safely with a clear dependency error when a package is unavailable. 3. Define exact reviewed versions in a lockfile. 4. Require cryptographic hashes for downloaded distributions, such as through `pip --require-hashes`. 5. Install dependencies during an explicit deployment phase inside an isolated virtual environment or container. 6. Configure a trusted package index and prevent dependency resolution from unexpected repositories. 7. Pin companion Skill versions and verify their publisher identity and artifact integrity. 8. Audit the exact versions of `anything-to-wechat` and `file-to-wechat` before granting them credentials or publishing access. 9. Use automated dependency vulnerability scanning and controlled update review rather than automatically accepting current releases. 10. Run installation and execution with the minimum filesystem, network, and account privileges required. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (17)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This is a clear mismatch. The declared description describes an end-to-end web-to-WeChat publishing tool, including scraping web content, intelligent formatting, image generation, and publishing to the WeChat draft box. The actual code only compresses an image file to satisfy WeChat file-size constraints. While image compression could be a supporting subcomponent in a larger WeChat publishing workflow, this code chunk by itself does not implement the declared primary behavior and lacks the core capabilities named in the description.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
声明的核心用途是“抓取网页并发布到微信公众号草稿箱”,还声称会自动生成封面图和配图、用 AI 智能整理格式。但代码实际功能是一个本地命令行网页抓取器:通过 requests 拉取网页,用 BeautifulSoup 提取文章内容,使用 html2text 转成 Markdown,并写入本地文件。代码支持若干站点选择器,能提取封面图片 URL,但不会生成图片;也没有任何微信公众号 API、认证、草稿箱上传、发布流程相关实现。因此其主要行为只覆盖了‘抓取网页内容并整理输出’这一部分,缺少声明中的关键后续能力,构成明显描述与行为不符。

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The README promotes scraping arbitrary web content, AI reformatting, image generation, and direct upload to a WeChat draft box without clearly warning that third-party content and account credentials will be transmitted and that the skill can perform external publishing actions. In this context, missing disclosure is security-relevant because users may not realize the privacy, copyright, and account-impacting consequences before invoking the skill.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The quick-start examples are broad natural-language triggers that can activate the skill for high-impact actions such as scraping external content and publishing to a WeChat account. Because the skill performs account-affecting operations, weak activation boundaries increase the risk of unintended invocation, especially in multi-skill or loosely routed agent environments.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill instructs use of shell, network access, and file writes but does not declare any explicit tool scope or permissions boundaries. That increases the chance an agent will execute high-impact actions implicitly, including fetching arbitrary URLs, writing transformed content, and publishing through companion scripts without a clearly constrained authorization model.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The trigger patterns are broad enough to match common conversation about reposting articles to WeChat, which can cause unintended activation of a skill that performs scraping, file generation, and publication workflows. Over-broad routing is dangerous here because the skill culminates in an account-affecting publish action, so accidental invocation could lead to unwanted drafts or handling of copyrighted/private content.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill explicitly instructs returning a published WeChat draft rather than a proposal, but does not require a clear warning or final user confirmation before performing a network action on the user's account. In this context, automatic publication to an authenticated third-party platform is materially risky because it can modify account state, publish unreviewed or copyrighted content, and expose the user to reputational or compliance harm.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The manifest description and tags indicate the skill is specifically for publishing to WeChat public accounts and uses Chinese-language framing, but there is no explicit user opt-in or documented locale constraint. Under the policy, forcing a specific language/locale without opt-in is a natural-language policy concern unless the region-specific constraint is clearly documented and justified.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
Auto-installing Pillow inside a helper script is unnecessary for the advertised image-compression function and introduces avoidable execution of external code from a package repository. In the context of a scraping-to-WeChat automation skill, this makes the skill more dangerous because it may run in unattended agent environments where implicit dependency installation can bypass review, alter the host, or expose systems to supply-chain compromise.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
except ImportError:
    print("[INFO] Installing Pillow...")
    import subprocess
    subprocess.check_call([sys.executable, "-m", "pip", "install", "Pillow", "-q"])
    from PIL import Image
Confidence
94% confidence
Finding
The script executes `pip install Pillow` automatically at runtime when `PIL` is missing, which causes network access and arbitrary package installation during normal use. This expands the trust boundary from local image processing to remote package retrieval and code execution, creating supply-chain and environment-manipulation risk if package sources, indexes, or the runtime environment are compromised.

Context-Inappropriate Capability

Medium
Confidence
98% confidence
Finding
The skill's purpose is to scrape and convert web pages, but it also silently installs Python packages if imports fail. That behavior is unrelated to the core user task and introduces supply-chain and environment-modification risk, especially if the skill runs in shared, privileged, or production-like environments.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The code launches package installation subprocesses automatically and gives only an informational print, not meaningful warning or consent. For an agent skill, this is dangerous because execution may be triggered by natural-language requests, causing unexpected software installation and persistent system changes.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
except ImportError:
    print("[INFO] Installing requests...")
    import subprocess
    subprocess.check_call([sys.executable, "-m", "pip", "install", "requests", "-q"])
    import requests

try:
Confidence
96% confidence
Finding
The script automatically invokes pip at runtime to install a missing dependency via a subprocess. This modifies the local environment and executes code fetched from package indexes without explicit user approval, which is risky in an agent skill that may run unattended on user systems.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
except ImportError:
    print("[INFO] Installing beautifulsoup4...")
    import subprocess
    subprocess.check_call([sys.executable, "-m", "pip", "install", "beautifulsoup4", "-q"])
    from bs4 import BeautifulSoup

try:
Confidence
96% confidence
Finding
This subprocess call auto-installs beautifulsoup4 when missing, causing implicit package installation during normal tool execution. Even though the command is not shell-injected, it still triggers external code retrieval and environment changes that exceed the expected scope of a scraping operation.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
except ImportError:
    print("[INFO] Installing html2text...")
    import subprocess
    subprocess.check_call([sys.executable, "-m", "pip", "install", "html2text", "-q"])
    import html2text
Confidence
96% confidence
Finding
This line auto-installs html2text through pip during execution, which can execute package installation logic and alter the runtime environment without informed consent. In an automation context, such hidden side effects increase supply-chain and operational risk.

Vague Triggers

Low
Confidence
80% confidence
Finding
The description says the skill can scrape "任意网页内容" and should be used whenever the user wants to scrape a web page and publish it to WeChat. This activation framing is very broad and does not clearly distinguish supported article-like pages from other ordinary web content, increasing ambiguity about when the skill should or should not run.

Natural-Language Policy Violations

Low
Confidence
97% confidence
Finding
The script hard-codes an Accept-Language header preferring zh-CN and zh, which can influence returned content language regardless of the user's preferences. This is a natural-language/locale policy concern because the file does not offer a language choice or explain why Chinese localization is required.

Static analysis

No suspicious patterns detected.