Back to skill

Security audit

Url Reader

Security checks for vulnerabilities and agentic risk

Overview

The skill is a plausible URL reader, but it needs review because it can send URLs/content to third-party fetchers, fetch arbitrary network resources, save files/images locally, and store reusable WeChat login state without enough safeguards.

Install only if you are comfortable with URLs and page content being processed by Firecrawl or Jina, with browser automation visiting the supplied pages, and with content/images being saved locally. Avoid private, tokenized, internal, or account-sensitive links. Do not set up WeChat login state unless you trust the local machine and can protect or delete the generated auth file.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/url_reader.py:431
Finding

Unrestricted URL Fetching Enables Server-Side Request Forgery

Content
View full analysis
list: """Extract image URLs from content.""" md_images = re.findall(r'!\[.*?\]\((https?://[^\s\)]+)\)', content) direct_images = re.findall( r'(https?://[^\s\)]+\.(?:jpg|jpeg|png|gif|webp|bmp)[^\s\)]*)', content, re.IGNORECASE ) xhs_images = re.findall(r'(https?://sns-webpic[^\s\)]+)', content) feishu_images = re.findall( r'(https?://[^\s\)]*feishu[^\s\)]+\.(?:jpg|jpeg|png|gif|webp)[^\s\)]*)', content, re.IGNORECASE ) qq_images = re.findall( r'(https?://docimg[^\s\)]+\.(?:jpg|jpeg|png|gif|webp)[^\s\)]*)', content, re.IGNORECASE ) all_images = list(dict.fromkeys( md_images + direct_images + xhs_images + feishu_images + qq_images )) return all_images def download_image(url: str, save_dir: Path, index: int) -> str: """Download an image and return its local filename.""" try: headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ' 'AppleWebKit/537.36', 'Referer': 'https://www.xiaohongshu.com/' } response = requests.get(url, headers=headers, timeout=30) response.raise_for_status() content_type = response.headers.get('content-type', '') if 'webp' in content_type or 'webp' in url: ext = '.webp' elif 'png' in content_type or 'png' in url: ext = '.png' elif 'gif' in content_type or 'gif' in url: ext = '.gif' else: ext = '.jpg' filename = f"img_{index:02d}{ext}" filepath ...[truncated 2538 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/wechat_reader.py:45
Finding

Reusable WeChat Authentication State Is Stored as Unprotected Plaintext

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
README.md:40
Finding

Unpinned Dependencies and Browser Downloads Create Supply-Chain Risk

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/url_reader.py:447
Finding

Unbounded Image Downloads Permit Memory and Disk Resource Exhaustion

Content
View full analysis
str: """Download an image and return its local filename.""" try: headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ' 'AppleWebKit/537.36', 'Referer': 'https://www.xiaohongshu.com/' } response = requests.get(url, headers=headers, timeout=30) response.raise_for_status() content_type = response.headers.get('content-type', '') if 'webp' in content_type or 'webp' in url: ext = '.webp' elif 'png' in content_type or 'png' in url: ext = '.png' elif 'gif' in content_type or 'gif' in url: ext = '.gif' else: ext = '.jpg' filename = f"img_{index:02d}{ext}" filepath = save_dir / filename with open(filepath, 'wb') as f: f.write(response.content) return filename except Exception: return None ``` All extracted images are processed without a count or aggregate-size limit: ```python images = extract_images_from_content(content) image_mapping = {} if images and verbose: print(f"Found {len(images)} images; downloading...") for i, img_url in enumerate(images, 1): local_name = download_image(img_url, content_dir, i) if local_name: image_mapping[img_url] = local_name ``` ### Technical Analysis `requests.get()` is used without streaming, so each response body is fully buffered in memory through `response.content` before being written. The implementation does not enforce: - A maximum `Content-Length` - A maximum number of bytes read from a response - A maximum number of images - An aggrega ...[truncated 1382 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
Findings (29)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

声明的核心能力是面向多平台的 URL 内容抓取与解析,而该代码片段只是一个本地保存器:输入是已有内容(字符串或文件),输出是本地 Markdown 和下载的图片。虽然它确实支持将内容保存为 Markdown 并下载图片到本地,这部分与声明一致,但缺少声明中最关键的上游能力:根据 URL 获取内容、识别来源平台、抽取正文。因此描述显著夸大了该代码块的实际行为,属于明显不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

声明描述的是一个完整的 URL 内容抓取与提取工具,包含平台自动识别、内容读取、核心内容提取、Markdown 保存和图片下载等功能。但该代码片段实际只做了域名匹配式的平台识别,并根据平台返回 strategy(如 browser/jina)、可选脚本名,以及构造 Jina Reader URL。它没有发起网络请求读取页面,没有解析正文,没有写入任何 Markdown 文件,也没有下载图片。因此代码实际行为与声明的主要功能存在明显不一致,属于描述显著夸大实现能力。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

描述宣称的是一个通用、多平台URL内容读取与本地保存工具,但代码实际是一个专用的“微信公众号文章读取器”。它依赖Playwright和微信登录态,核心流程包括扫码登录、保存storage state到本地JSON、加载认证状态访问公众号文章、提取文本和图片链接。代码没有任何平台识别逻辑,也没有针对其他平台的处理分支;没有把Markdown写入文件;也没有下载图片到本地。因此其主要用途和能力范围都明显窄于声明,且还包含未声明的微信认证状态管理能力,属于明显描述与行为不符。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

声明描述的是一个通用、多平台内容读取与保存工具,但这段代码的核心功能明显更窄,只针对微信公众号文章。它通过特定选择器(如 #js_content、#activity-name)和微信 UA 进行抓取,且专门处理微信环境异常/验证流程,说明其主要目的并非“任意URL、多平台自动识别”。此外,代码没有将结果写入 Markdown 文件,也没有任何图片下载逻辑。虽然格式化输出接近 Markdown,但仅输出到终端不能等同于“自动保存为Markdown”。另外,代码会将认证状态写入本地 JSON 文件,这属于声明中未提及的持久化能力。综上,描述与实际行为存在实质性不符。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The description presents a broad web content ingestion and extraction skill covering multiple Chinese platforms with content saving and image downloading. The supplied code only handles one specific task: converting WeChat public-account long URLs to short URLs. It launches a browser, visits the provided WeChat URL, inspects redirects/meta tags/page source, and returns a shortened article URL if found. This is a materially different primary purpose from the declared description, with most advertised capabilities absent.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill routes user-supplied URLs and fetched page content through Firecrawl and Jina, but it does not prominently warn users that their requested targets and retrieved data may be transmitted to third-party services. This can leak sensitive URLs, private document links, tokens embedded in URLs, or proprietary page contents to external processors without informed consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The README explicitly advertises automatic saving of page content and downloaded images to local storage, but does not warn users about filesystem side effects, storage growth, or where data will be written. In an agent skill context, undocumented writes can surprise users, persist sensitive or copyrighted material, and create downstream privacy or disk-consumption risks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README describes a retrieval pipeline that sends URLs and potentially page content through external services such as Firecrawl and Jina, with Playwright as a fallback for dynamic or login-gated pages, yet it does not disclose the data-sharing implications. This is dangerous because users may unknowingly transmit sensitive URLs, session-accessible content, or scraped page data to third parties or process authenticated pages without understanding the privacy boundary.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill description is written entirely in Chinese and presents the skill in a single language with no indication that users can choose another language or that the skill is region-specific. Under the policy, forcing a specific language or locale without opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script hard-codes a user-specific output directory under /Users/ys/..., causing all saved content to be written to a fixed local location without requiring explicit user selection. In an agent skill that processes arbitrary URLs and content, this creates unintended persistence and scope expansion, and may leak or overwrite data in a sensitive personal knowledge-base path.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script automatically extracts external image URLs from untrusted content, performs network requests to fetch them, and writes the results to local disk with no explicit user consent or safety checks. This is dangerous because arbitrary content can trigger outbound requests to attacker-controlled hosts, cause local persistence of untrusted files, and enable tracking or resource-consumption behavior beyond the user's likely expectations for a generic URL reader.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

When the tool constructs and displays a Jina Reader URL from an arbitrary user-supplied URL, it implicitly routes the target resource through an external third-party service. In the context of a URL-reading skill that claims to read arbitrary links, this can expose private, internal, tokenized, or otherwise sensitive URLs to Jina without any explicit warning or consent, creating a real privacy and data-handling risk.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The code explicitly loads a local WeChat authenticated browser state file and later uses it in Playwright to access content behind login or access controls. That expands the skill from generic public URL reading into acting with the user's stored identity, which can expose private or account-scoped content and create unintended data access if invoked on attacker-supplied URLs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code forwards user-supplied URLs to external services such as Jina Reader, and Firecrawl is also used elsewhere, without an explicit warning that the destination URL and fetched content may be disclosed to third parties. This creates privacy and data-handling risk, especially if the URL contains sensitive query parameters or points to internal, private, or user-specific content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The browser context is initialized with a local WeChat storage state file when present, but the user-facing flow does not clearly warn that existing authenticated session material will be applied to requests. This can cause the skill to access account-scoped pages and leak session-derived data under the guise of simple URL reading.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The Playwright fallback does more than render a page: it detects anti-bot or verification pages and attempts to click a verification button automatically. That behavior crosses from passive reading into active interaction with access/verification flows, which can bypass user expectations, trigger site actions, and increase abuse potential on untrusted URLs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script saves Playwright storage state, which can include session cookies and other authentication artifacts, to a local JSON file without clearly warning the user about the sensitivity of this data or protecting it. If another local user, process, or included tooling accesses this file, the stored WeChat session could be reused to impersonate the user within the preserved session scope.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest describes a URL reader that automatically saves content as Markdown and downloads images locally. In this implementation, read_article only extracts title/content/image URLs, and main merely prints formatted text to stdout; there is no code that writes Markdown files or downloads image data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script persists Playwright storage state, which can include cookies and other session artifacts, to a predictable local JSON file without access controls, encryption, or a clear user warning. If that file is read by another local user, process, or bundled/uploaded unintentionally, an attacker may reuse the authenticated browser session to access the associated WeChat context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file’s natural-language interface and documentation are entirely in Chinese, including the tool description and usage/help strings, with no indication that language is user-selectable. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless clearly justified as region-specific.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill emphasizes automatic saving of content and images to a fixed local directory but does not present this as a user-facing warning or consent boundary. Users may unintentionally persist sensitive article contents, private URLs, or downloaded media on disk, creating privacy, retention, and multi-user exposure risks.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The activation examples are broad enough to match ordinary requests like 'read this link' or 'look at this page,' which can cause the skill to trigger in routine conversations without the user realizing a specialized tool will be used. In this skill, unintended activation is more dangerous because the tool may fetch remote content and save content/images locally, potentially exposing data to third-party services and creating unwanted local artifacts.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The visible title, feature descriptions, and usage examples are all presented in Chinese, and the example invocations assume Chinese-language interaction. Because the file does not state that the skill is region-specific or offer alternative language support, this may violate a language/locale policy requiring user choice or documented justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

Natural-language strings in the module docstring and CLI output are presented only in Chinese, with no mechanism for language selection or indication that the tool is intentionally region-specific. This can violate language/locale policy when users are not given a choice.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.