Back to skill

Security audit

Wechat Article To Markdown

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it claims, but it can fetch arbitrary URLs and renders remote pages with Chromium sandboxing disabled, which deserves Review before installation.

Install only if you are comfortable giving this skill outbound network access and local output-directory write access. Use it only with trusted WeChat article URLs, prefer running it in a sandboxed/containerized environment, and avoid using it on untrusted or non-WeChat links until host allowlisting and browser sandboxing 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
scripts/wechat_to_md.py:64
Finding

Unrestricted URL Fetching and Redirect Handling Permit Server-Side Request Forgery

Content
View full analysis
str: raw = raw.strip() raw = html_unescape(raw) if raw.startswith("//"): raw = "https:" + raw if not raw.startswith("http"): raw = "https://" + raw return raw ``` The normalized URL is passed directly to Playwright: ```python page.goto(url, wait_until="domcontentloaded", timeout=timeout) ``` The fallback HTTP client follows redirects without validating their destinations: ```python resp = session.get(url, timeout=20, allow_redirects=True) resp.raise_for_status() resp.encoding = resp.apparent_encoding or "utf-8" return resp.text ``` Arbitrary HTTP image sources found in article content are accepted: ```python data_src = img.get("data-src", "") if data_src and ("mmbiz" in data_src or data_src.startswith("http")): img["src"] = data_src if data_src not in seen: seen.add(data_src) img_urls.append(data_src) src = img.get("src", "") if src and src not in seen and ("mmbiz" in src or src.startswith("http")): seen.add(src) img_urls.append(src) ``` Those image URLs are downloaded while redirects remain enabled: ```python resp = requests.get( url, timeout=timeout, headers=DEFAULT_HEADERS, stream=True, allow_redirects=True ) resp.raise_for_status() ``` ### Technical Analysis The documentation states that the Skill supports only `mp.weixin.qq.com` articles, but this restriction is not enforced in code. `normalize_url()` adds a scheme without validating: - The exact hostname - The URL scheme - The destination port - Embedded credentials - The resolved IPv4 or IPv6 address - Redirect destinations - Image CDN destinations Consequently, a caller can supply an arbitrary external, loopback, private-network, ...[truncated 2448 chars]
Remediation
View remediation
str: parsed = urlparse(url) if parsed.scheme != "https": raise ValueError("Only HTTPS URLs are allowed") if parsed.hostname != "mp.weixin.qq.com": raise ValueError("Only mp.weixin.qq.com is allowed") if parsed.username or parsed.password: raise ValueError("Embedded credentials are not allowed") if parsed.port not in (None, 443): raise ValueError("Nonstandard ports are not allowed") return url ``` 2. Resolve the hostname and reject every loopback, private, link-local, multicast, reserved, and unspecified IPv4 or IPv6 result. 3. Prevent DNS rebinding by validating the resolved address immediately before connection and ensuring the client connects to the validated destination. 4. Disable automatic redirects. If redirects are required, inspect and validate every redirect target before following it. 5. Apply a separate exact-host allowlist to images, limited to explicitly approved WeChat CDN domains. Do not use substring checks such as `"mmbiz" in URL`. 6. Validate image redirect destinations using the same hostname and IP-address controls. 7. Add outbound firewall or container-network rules that deny access to loopback, RFC1918 networks, link-local networks, cloud metadata addresses, and other sensitive ranges. 8. Add tests covering direct private addresses, IPv6 loopback, encoded hosts, user-information confusion, nonstandard ports, DNS rebinding, and external-to-internal redirects. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/wechat_to_md.py:117
Finding

Chromium Sandbox Is Disabled While Rendering Untrusted Remote Pages

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (9)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 54)May include surrounding context.

md
python scripts/wechat_to_md.py "<WECHAT_URL>" -o "<OUTPUT_DIR>"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 60)May include surrounding context.

md
python scripts/wechat_to_md.py "<WECHAT_URL>" -o "<OUTPUT_DIR>"

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · references/wechat-dom-reference.md (reported line 61)May include surrounding context.

3.1 标题

html
<!-- H2 标题 -->
<h2 style="text-align: center; font-size: 22px;">标题文本</h2>

<!-- 自定义标题(通过 section 模拟) -->

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · references/wechat-dom-reference.md (reported line 61)May include surrounding context.

3.1 标题

html
<!-- H2 标题 -->
<h2 style="text-align: center; font-size: 22px;">标题文本</h2>

<!-- 自定义标题(通过 section 模拟) -->

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/wechat_to_md.py (reported line 133)May include surrounding context.

python
"--disable-backgrounding-occluded-windows",
                "--disable-popup-blocking", "--disable-prompt-on-repost",
                "--disable-sync", "--enable-async-dns",
                "--use-mock-keychain",
                "--hide-scrollbars", "--mute-audio",
                "--disable-extensions",
            ],

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill instructs the agent to install packages, execute a Python script, fetch remote WeChat content, and write Markdown/images to disk, but it does not declare any explicit tool scope such as allowed-tools or permissions. That creates an authorization gap: an agent/runtime may grant broader shell, network, and file-write capabilities than users expect, increasing the risk of unintended command execution, uncontrolled outbound requests, or arbitrary file creation if the skill is invoked on adversarial input.

Content

No source excerpt is available for this finding.

Tainted flow: 'filepath' from requests.get (line 828, network input) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/wechat_to_md.py (reported line 836)May include surrounding context.

python
if existing_size > 100:  # 至少 100 字节
                        return url, str(filepath)

                with open(filepath, "wb") as f:
                    for chunk in resp.iter_content(8192):
                        if chunk:
                            f.write(chunk)

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

This markdown file contains user-facing instructional content exclusively in Chinese and does not indicate that language selection is optional. Under the natural-language policy rule, forcing a specific language without user opt-in is a locale-policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The Playwright browser context is hard-coded to use locale="zh-CN" and timezone_id="Asia/Shanghai". This imposes a specific locale on all users and matches the policy category for language/locale constraints without user choice or opt-in.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.