Back to skill

Security audit

wechat-mick

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly matches its WeChat article summary purpose, but its backup fetcher can retrieve arbitrary user-supplied URLs from the agent environment.

Review before installing. The useful behavior is straightforward, but it should be restricted to HTTPS WeChat article URLs, validate redirects and private or metadata IP ranges, and disclose or ask before using the Python fallback. Avoid using it in environments where the agent can reach internal services until those limits are added.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fetch_article.py:22
Finding

Server-Side Request Forgery Through Unvalidated User-Supplied URLs

Content
View full analysis

Vulnerability Details

File Location: scripts/fetch_article.py:22-44, 180-185; related workflow guidance in SKILL.md:21-25, 92-93
Vulnerability Type: Server-Side Request Forgery (SSRF) caused by insufficient URL validation
Risk Level: High

Vulnerable Code

python
def fetch_wechat_article(url: str) -> dict:
    """
    Fetch a WeChat public-account article.

    Args:
        url: Public-account article URL

    Returns:
        dict: Dictionary containing title, author, and content
    """
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
        'Accept-Encoding': 'gzip, deflate, br',
        'Connection': 'keep-alive',
        'Upgrade-Insecure-Requests': '1',
        'Cache-Control': 'max-age=0',
    }

    try:
        response = requests.get(url, headers=headers, timeout=30)
python
def main():
    if len(sys.argv) < 2:
        print("Usage: python fetch_article.py <article URL> [--json]")
        sys.exit(1)

    url = sys.argv[1]
    output_json = '--json' in sys.argv

    result = fetch_wechat_article(url)

The related Skill workflow explicitly allows attempts to retrieve non-WeChat URLs:

markdown
- If it is not a WeChat public-account link, still attempt to summarize it, but remind the user that this Skill is primarily optimized for public-account articles.

Technical Analysis

The script passes a user-controlled command-line URL directly to requests.get() without validating:

  • The URL scheme
  • The destination hostname
  • The resolved IP address
  • The destination port
  • Redirect destinations
  • Whether the destination belongs to an approved WeChat domain

...[truncated 2251 chars]

Remediation
View remediation

Remediation Suggestions

  1. Restrict retrieval to HTTPS URLs whose normalized hostname exactly equals mp.weixin.qq.com or belongs to a narrowly defined, reviewed allowlist.
  2. Reject URLs containing embedded credentials, fragments where unnecessary, malformed hostnames, nonstandard ports, or unsupported schemes.
  3. Resolve the hostname before connecting and reject every address in loopback, private, link-local, multicast, reserved, unspecified, and other non-public ranges for both IPv4 and IPv6.
  4. Disable redirects with allow_redirects=False, or manually process redirects and repeat the full scheme, hostname, port, DNS, and IP validation for every redirect target.
  5. Protect against DNS rebinding by ensuring that the validated address is the address used for the connection and by validating every newly resolved redirect host.
  6. Explicitly block cloud metadata destinations, including link-local metadata addresses, as defense in depth.
  7. Remove the instruction to fetch arbitrary non-WeChat URLs. Reject unsupported domains rather than attempting retrieval.
  8. Apply strict response-size and content-type limits to reduce resource-exhaustion risk.
  9. Enforce outbound firewall or proxy rules so the Skill runtime cannot reach internal networks or metadata services.
  10. Add automated tests covering direct private addresses, IPv6 loopback, alternative IP representations, embedded credentials, unusual ports, DNS rebinding scenarios, and public-to-private redirects.
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (8)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The stated purpose is summarization, but the instructions direct the agent to retrieve full article contents, metadata, and to output raw content to itself before summarizing. This mismatch hides material behavior from users and reviewers, and it increases data exposure risk because the skill is effectively a content-extraction/fetching tool, not just a summarizer.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill performs network-capable actions via WebFetch and a Python fallback, but it does not declare an explicit tool scope such as allowed-tools or permissions. This weakens least-privilege controls and makes the skill's effective capabilities less transparent to reviewers and runtime policy enforcement.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

L03 将“帮我看看这篇文章讲什么”“总结一下这个链接”等常见表达列为触发条件,并进一步写明“只要看到 mp.weixin.qq.com 的链接并且用户想了解内容,就应该使用这个 skill”。这类表述缺少更明确的边界或排除条件,容易与普通对话中的常见请求重叠,造成意外调用。

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill silently falls back to a Python script when WebFetch encounters anti-bot or validation pages, without explicit user notice or consent. This is risky because it changes the execution mode to a more opaque and potentially more powerful scraping path, which can surprise users and bypass expected transparency around remote access behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

L30 要求“生成中文总结”,且 L62 再次规定“中文输出”。这是自然语言层面的语言策略约束,但文档未提供用户选择语言的选项,也未说明该限制具有区域合规或业务上的必要性。

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script accepts any user-supplied URL and passes it directly to requests.get without validating that it belongs to mp.weixin.qq.com. In an agent context, this creates an SSRF-capable network primitive that can be abused to reach internal services, cloud metadata endpoints, or other unintended destinations, which is more dangerous than a normal article-fetch helper because the skill is supposed to be narrowly scoped to WeChat article summarization.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The docstring states the script is 'used to bypass cases where WebFetch cannot retrieve content,' framing the code as a workaround to evade another fetch mechanism's limits rather than merely retrieving WeChat article content. That documented intent diverges from the skill's stated purpose of summarizing WeChat articles when given a WeChat article link.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The request header forces 'zh-CN,zh;q=0.9,en;q=0.8', which expresses a fixed language/locale preference. Under the policy, locale constraints should be user-selectable or clearly justified; this file contains no such opt-in or justification.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.