Back to skill

Security audit

Shopping Advisor

Security checks for vulnerabilities and agentic risk

Overview

This skill is a shopping advice helper with small local demo scripts and no evidence of hidden access, persistence, payments, or data exfiltration.

Install this if you want a lightweight shopping comparison helper, especially for Chinese ecommerce contexts. Treat its output as advice only, verify live prices and seller details yourself, and avoid feeding untrusted product text into Markdown or terminal workflows that treat formatted output as authoritative.

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

Note
Location
scripts/analyze.py:20
Finding

Untrusted Terminal and Markdown Output Injection

Content
View full analysis

Vulnerability Details

File Location: scripts/analyze.py, lines 20-23 and 43-48
Vulnerability Type: Unsanitized rendering of attacker-controlled structured input
Risk Level: Low

Vulnerable Code

python
payload = read_stdin_json()
context = payload.get("shopping_context") or {}
report = payload.get("decision_report") or {}
query = context.get("query") or {}
candidates = context.get("candidates") or []
python
for candidate in candidates:
    price = ((candidate.get("price") or {}).get("final_price"))
    source = candidate.get("source") or "unknown"
    relation = ((candidate.get("comparison") or {}).get("relation")) or "same_item"
    line = f"- {candidate.get('id')}: {candidate.get('title')}"

The constructed line is subsequently printed without sanitization:

python
print(line)

Other attacker-controlled fields, including category, scenario, priorities, pitfalls, alternative directions, candidate identifiers, and the final decision, are rendered using the same unsafe pattern.

Technical Analysis

analyze.py reads arbitrary JSON from standard input and directly renders values from that JSON into terminal or Markdown output. Although the project includes schema.json, the script does not validate its input against that schema. It also does not enforce string length limits, verify expected scalar and collection types, escape Markdown syntax, or remove terminal control characters.

An attacker can place ANSI escape sequences in a candidate title or another displayed field to manipulate terminal presentation. In a Markdown consumer, crafted headings, links, images, or list syntax can inject misleading sections into the generated report. This is an output-injection issue rather than command injection: the reviewed implementation does not pass these values to a shell, interpreter, or network client.

Attack Path

  1. An attacker prepares a JSON payload containing a malicious candidate title or report field.
  2. The ...[truncated 960 chars]
Remediation
View remediation

Remediation Suggestions

  1. Validate every input to analyze.py against schema.json before rendering it.
  2. Enforce expected types and explicit maximum lengths for titles, identifiers, categories, priorities, decisions, pitfalls, and alternative directions.
  3. Remove unsafe C0 and C1 terminal control characters, including escape characters, while retaining only explicitly permitted whitespace.
  4. Escape Markdown metacharacters when output is intended to be Markdown, especially in user-controlled titles and free-text fields.
  5. Reject unexpected nested objects or arrays instead of implicitly converting or joining them.
  6. Keep terminal-safe text rendering separate from Markdown rendering so each output format can apply appropriate encoding.
  7. Add regression tests using ANSI escape sequences, embedded headings, deceptive links, multiline values, and oversized strings.
Vulnerability Patterns
  • 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
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (15)

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.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases are extremely generic, such as 'help me choose one' or 'tell me directly how to buy,' which overlap with ordinary conversation outside shopping contexts. This can cause unintended invocation, leading the agent to switch into shopping-advice behavior when the user did not intend to use this skill, increasing the risk of confusion, context hijacking, or inappropriate recommendations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The document prescribes response style and final recommendation phrasing in Chinese, but does not indicate that language should follow the user's preference or be opt-in. This can violate language/locale policy expectations when users interact in other languages.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This manifest/config file hard-codes a default currency of "CNY", which imposes a locale-specific assumption in the skill's natural-language/data policy surface. Because the schema does not indicate user opt-in, configurability, or region-specific justification, it can steer behavior toward a specific locale by default.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

A second locale-specific default appears in the price object, again forcing "CNY" unless overridden. Repeating this assumption across the schema increases the chance that the skill will consistently operate in a specific locale without explicit user choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script emits multiple hard-coded Chinese strings such as '未知候选', '未提供', and several full Chinese guidance sentences, with no logic to detect or request the user's preferred language. This creates a natural-language policy issue because the skill enforces a specific locale rather than offering a choice or documenting a justified regional restriction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This Python file contains user-facing natural-language responses in Chinese, and the behavior appears consistent throughout the skill. Because the skill forces a specific language without any visible opt-in or documented region-specific justification in this file, it violates the language/locale policy requirement.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The main decision messages presented to users are written exclusively in Chinese, including budget guidance and recommendation text. This indicates the skill's user-visible behavior is locked to one language rather than adapting to or requesting the user's preferred locale.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The changelog entries are presented exclusively in Chinese, which may imply a language-specific constraint without any accompanying note that the skill is intended only for Chinese-speaking users or that language choice is configurable. Under the policy, forcing a specific language without user opt-in can be a natural-language policy issue.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest presents the skill title bilingually but the summary is only in Chinese, which indicates a language-specific user experience without any stated opt-in or locale justification. Under the policy, forcing a specific language without user choice can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The package description is written entirely in Chinese and provides no indication that users can choose another language or locale. This can violate a language/locale policy when the skill is presented to a broader audience without explicit opt-in or documented regional scope.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

This JSON example uses only Chinese field values such as "投影仪" and "卧室夜间看电影", which implies a fixed language/locale context. Because there is no indication that language is optional, user-selectable, or justified as region-specific, this can conflict with the policy against forcing a specific language without user opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

This JSON file encodes user-facing category, scenario, priorities, and notes entirely in Chinese, which can indicate a fixed language/locale assumption. Under the policy rule, forcing a specific language without opt-in is a natural-language policy concern unless the locale restriction is clearly documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

This JSON input contains user-facing natural-language values such as category, scenario, notes, and item titles entirely in Chinese. Because SQP-3 applies to all file types, a file that effectively assumes a single language without any opt-in or alternative can be considered a locale-policy issue.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The instructional text in this markdown file is written in Chinese and does not indicate that users may choose another language or that the skill is intentionally limited to a Chinese-speaking audience. Under the stated policy, forcing a specific language without opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.