Back to skill

Security audit

wechat-article-explainer

Security checks for vulnerabilities and agentic risk

Overview

This skill is meant to summarize WeChat articles, but its fetcher can access arbitrary URLs without enforcing the WeChat-only scope.

Install only if you are comfortable with a skill that runs a local Python fetcher and headless browser. Use it only with trusted WeChat article links, preferably in a sandboxed environment without access to internal networks or sensitive local files, and consider adding strict mp.weixin.qq.com URL validation plus pinned dependencies before broader use.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/wechat_reader.py:207
Finding

Missing URL Validation Enables Server-Side Request Forgery

Content
View full analysis
dict: """ 解析微信 URL,提取关键信息 Args: url: 微信公众号文章链接 Returns: 包含 URL 信息的字典 """ # 微信文章 URL 模式 patterns = [ r'https?://mp\.weixin\.qq\.com/s/([a-zA-Z0-9_-]+)', # 直接文章 ID r'https?://mp\.weixin\.qq\.com/s\?([a-zA-Z0-9&=_-]+)', # 带参数的 URL r'https?://mp\.weixin\.qq\.com/profile/([a-zA-Z0-9_-]+)', # 公众号主页 ] result = { "original_url": url, "type": "unknown", "article_id": None, "params": {} } # 提取文章 ID match = re.search(r'/s/([a-zA-Z0-9_-]+)', url) if match: result["type"] = "article" result["article_id"] = match.group(1) # 提取 URL 参数 if '?' in url: query_string = url.split('?')[1] params = {} for param in query_string.split('&'): if '=' in param: key, value = param.split('=', 1) params[key] = value result["params"] = params return result ``` ```python def fetch_article(url: str, use_browser: bool = True) -> dict: """ 获取微信文章内容 Args: url: 微信公众号文章链接 use_browser: 是否使用浏览器模式(更稳定但更慢) Returns: 包含文章内容的字典 """ # 先解析 URL url_info = parse_wechat_url(url) print(f"解析 URL: {json.dumps(url_info, ensure_ascii=False, indent=2)}", file=sys.stderr) if use_browser and PLAYWRIGHT_AVAILABLE: return fetch_article_with_playwright(url) else: return fetch_article_with_requests(url) ``` ### Technical Analysis The Skill is documented as accepting only WeChat article URLs under `mp.weixin.qq.com`. Although `parse_wechat_url()` defines several expected URL patterns, the `patterns` list is never used to validate or rej ...[truncated 2561 chars]
Remediation
View remediation
` or `/s` with expected query parameters. 3. Resolve the hostname and reject any destination resolving to loopback, private, link-local, multicast, reserved, or otherwise non-public addresses using Python's `ipaddress` module. 4. Prevent DNS rebinding by ensuring the validated address is the address used for the connection, or enforce destination restrictions at an outbound proxy or firewall. 5. Disable automatic redirects or validate the scheme, hostname, port, and resolved address of every redirect destination before following it. 6. In Playwright mode, intercept navigation and subresource requests with routing rules and abort requests to all origins except an explicit allowlist. 7. Reject malformed, unknown, or unsupported URLs rather than merely recording `"type": "unknown"`. 8. Add tests covering localhost, private IPv4 and IPv6 ranges, link-local metadata addresses, encoded hostnames, user-information tricks, alternate ports, protocol-relative URLs, and redirect chains. ]]>

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unbounded Third-Party Dependencies Create a Non-Reproducible Supply Chain

Content
View full analysis
=2.28.0 playwright>=1.40.0 ``` Related installation instructions: ```bash pip install requests # 或使用浏览器模式 pip install playwright playwright install chromium ``` ### Technical Analysis The dependency declarations specify only minimum versions and do not impose an upper bound, exact version, or integrity hash. The documented commands are even less constrained because they install the latest available versions of `requests` and `playwright`. The instructions also run `playwright install chromium`, which downloads a browser component outside the Python dependency lock process. No reviewed browser revision, artifact hash, or trusted mirror is specified in the project. As a result, two installations of the same Skill version can receive materially different executable dependencies. Future package releases or browser artifacts are implicitly trusted without being part of this audit. This increases exposure to compromised upstream releases, registry account compromise, malicious package-index substitution, and unexpected compatibility or security regressions. No evidence in the reviewed project shows that the current named packages are malicious. The issue is the unsafe and non-reproducible dependency acquisition policy. ### Attack Path 1. A user follows `SKILL.md` or installs the packages from `requirements.txt`. 2. The package index resolves any versions satisfying the open-ended `>=` constraints, or resolves the latest versions when the documented direct installation commands are used. 3. Playwright subsequently downloads a Chromium artifact through its installation mechanism. 4. If a resolved package release, package source, or downloaded browser artifact has been compromised, malic ...[truncated 1103 chars]
Remediation
View remediation
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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
95% confidence
Finding

The declared skill purpose suggests simple article explanation, but the implementation includes undisclosed external fetching behavior and support for writing results to local JSON files. This mismatch is dangerous because reviewers and users may approve or invoke the skill without realizing it can perform network operations and create local artifacts, enabling unexpected data exfiltration, persistence, or misuse of fetched content.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill instructs the agent to execute a Python script that performs external network access and reportedly can write output locally, but the manifest declares no explicit tool scope or permissions. This creates an authorization gap where the agent may use broader capabilities than users or reviewers expect, increasing the risk of unintended data access, outbound requests, or file creation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code file contains user-facing natural-language strings entirely in Chinese, including the module docstring and command-line help text, which effectively imposes a specific language on users. The file does not offer an opt-in language choice or explain that the tool is intentionally limited to a Chinese-only regional audience, which matches the locale-policy violation criteria.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The tool is described as a WeChat article reader, but it accepts any user-supplied URL and passes it directly to Playwright or requests without validating that the destination is actually under mp.weixin.qq.com. In an agent or server environment, this creates a classic SSRF capability that can be used to reach internal services, cloud metadata endpoints, or other unintended network targets under the guise of article fetching.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
92% confidence
Finding

The dependency is specified with a lower bound only, which allows future installs to resolve to different versions over time and prevents reproducible builds. This increases supply-chain risk and makes it difficult to verify whether a deployed version includes known security fixes or newly introduced vulnerabilities.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
requests>=2.28.0
playwright>=1.40.0

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
82% confidence
Finding

The manifest includes requests without an exact version, while the package has multiple published advisories across releases. Because this skill consumes user-supplied URLs and may make outbound requests to attacker-controlled endpoints, inability to verify the installed requests version creates avoidable risk, including exposure to URL- or credential-handling flaws present in some releases.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
92% confidence
Finding

The Playwright package is also unpinned, so installations are not deterministic and may pull in different versions and transitive dependencies over time. For a skill that fetches and renders untrusted web content, dependency drift increases exposure to browser automation and parsing flaws introduced upstream.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
requests>=2.28.0
playwright>=1.40.0

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The --output parameter allows writing fetched content to an arbitrary filesystem path, which exceeds the stated purpose of merely reading/explaining article content. In an automated agent context, an attacker who can influence arguments may overwrite application files, drop data into sensitive locations, or abuse the skill as a file-write primitive.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.