Back to skill

Security audit

购物比价师

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed shopping price comparison helper that relies on public search results and does not show credential use, persistence, scraping, or hidden high-impact actions.

Before relying on this skill, treat its prices and links as preliminary search-result summaries. Verify final prices and destination URLs directly on the official shopping platforms, especially for expensive purchases, and do not use it for bulk commercial monitoring.

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

Warning
Location
scripts/price_checker.py:173
Finding

Unescaped External Search Data Allows Markdown Content Injection

Content
View full analysis

Vulnerability Details

File Location: scripts/price_checker.py, lines 173-177 and 196-201
Vulnerability Type: Markdown injection through unescaped product titles and unvalidated URLs
Risk Level: Medium

Vulnerable Code

python
for i, product in enumerate(sorted_products[:10], 1):
    platform_name = self.PLATFORM_MAPPING.get(
        self._detect_platform(product.platform), 
        {'name': product.platform}
    )['name']
    
    price_display = f"¥{product.estimated_price:.2f}" if product.estimated_price else "未显示"
    title_snippet = product.title[:30] + "..." if len(product.title) > 30 else product.title
    
    row = f"| {i} | {platform_name} | {title_snippet} | {price_display} | [查看]({product.url}) |"
    report_lines.append(row)
python
for i, product in enumerate(sorted_products[:5], 1):
    platform_name = self.PLATFORM_MAPPING.get(
        self._detect_platform(product.platform),
        {'name': product.platform}
    )['name']
    
    report_lines.extend([
        f"### {i}. {platform_name}",
        f"- **商品**: {product.title}",
        f"- **价格**: ¥{product.estimated_price:.2f} (如果显示)" if product.estimated_price else "- **价格**: 未在摘要中显示",
        f"- **来源**: 搜索引擎索引结果",
        ""
    ])

Technical Analysis

generate_report() treats ProductInfo.title, ProductInfo.platform, and ProductInfo.url as trusted values and directly interpolates them into a Markdown document. These fields are intended to originate from external search results, where listing publishers can control product titles and destination URLs.

Markdown metacharacters, table separators, line breaks, headings, links, and images are not escaped. Consequently, a crafted title can terminate the intended table cell or list item and insert attacker-controlled report content. The destination URL is also placed inside a Markdown link without parsing its scheme or verifying that i ...[truncated 2047 chars]

Remediation
View remediation

Remediation Suggestions

  1. Escape Markdown metacharacters in every externally sourced text field before interpolation, including product titles and platform names.
  2. Replace carriage returns and line feeds in values used inside tables or list items so an input value cannot create new Markdown blocks.
  3. Parse URLs with urllib.parse.urlparse() and allow only the https scheme.
  4. Verify destination hosts against an explicit allowlist for the detected platform. Reject mismatches rather than displaying them as trusted platform links.
  5. Reject URLs containing credentials, control characters, malformed encoding, or unexpected schemes.
  6. Consider displaying validated URLs as plain text when the report renderer's link-scheme policy is unknown.
  7. Keep untrusted search snippets separate from authoritative recommendations and clearly label their origin.
  8. Add tests using titles containing pipes, brackets, parentheses, headings, image syntax, and line breaks, as well as URLs with disallowed schemes and unrelated hosts.
  9. Apply output encoding at the final rendering boundary if reports may also be converted to HTML.
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (8)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The quick-start section instructs users to query the skill in Chinese and all example invocations are Chinese-language prompts. While the file includes some bilingual headings, it does not explicitly state that users may interact in other languages, which can amount to a language/locale constraint without opt-in.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The activation guidance says '当需要购物时,直接告诉我你想买的商品' and then provides broad example utterances. This does not clearly define when the skill should activate versus ordinary shopping conversation, and it lacks negative examples or narrower trigger constraints.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The user-facing quick-start instructions and all invocation examples are presented only in Chinese, effectively steering usage toward a single language. While the document is bilingual in places, it does not explicitly offer the user a language choice for interaction or outputs.

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 emits Chinese-only status messages and later generates a Chinese-language report and recommendations, while the CLI description and filename do not indicate that the skill is intentionally China-region or Chinese-language only. That creates a natural-language locale policy issue because the skill imposes a specific language without user opt-in or an explicit documented constraint.

Content

No source excerpt is available for this finding.

Scope Creep

Low
Category
Excessive Agency
Confidence
70% confidence
Finding

Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Content

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

md
### ⚠️ Disclaimers / 免责条款

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

This markdown file contains operational guidance expressed partly in Chinese, including search query examples and evaluation indicators, but does not indicate that the skill supports multiple languages or that Chinese is a required locale. Under the policy, forcing or assuming a specific language without user opt-in can be a natural-language policy issue.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The top-level docstring and PriceChecker/search_public_info documentation describe a working 'price checker' that uses web_search to gather public price information, but the implementation explicitly avoids calling any tool and instead returns a query template and instruction string. This is an intent/documentation mismatch because the code presents itself as an operational checker while the actual behavior is scaffolding only.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

The function documentation describes concrete parsing behavior, including extracting visible product data from search snippets. In reality, the body contains only placeholder comments and returns no parsed products, directly contradicting the documented intent.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.