Back to skill

Security audit

Used Market Watch

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent Korean used-market monitoring skill, but it needs review because it emits shell/cron command strings built from user-controlled rule names.

Install only if you are comfortable with a Korean-market scraper that sends your search terms to marketplace/search sites and stores watch state locally. Do not directly execute generated command or cron strings from untrusted user text; have automation call the script with argument arrays or properly escaped arguments, and review any scheduled job before enabling it.

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

Warning
Location
scripts/watch_intent.py:124
Finding

Shell Command Injection Through User-Controlled Rule Names

Content
View full analysis
str: quoted = re.search(r'"([^"]{2,40})"', text) if quoted: return quoted.group(1).strip() ``` ```python def _build_plan_hints(name: str, delivery_mode: str, schedule: dict[str, Any]) -> dict[str, Any]: command = f'python {SCRIPT_PATH} watch-check "{name}" --json' if delivery_mode == "alert": command = f'python {SCRIPT_PATH} watch-check "{name}" --alerts-only --json' persist_command = f'python {SCRIPT_PATH} watch-upsert {{request_json}}' return { "recommended_command": command, "persist_command_template": persist_command, "cron": schedule.get("cron"), "cron_example": f'{schedule["cron"]} {command}' if schedule.get("cron") else None, } ``` ```python recommended_command = (rule.get("plan_hints") or {}).get("recommended_command") persist_command = f'python {SCRIPT_PATH} watch-upsert {text!r}' cron_payload = None if schedule.get("cron"): cron_payload = { "expr": schedule["cron"], "command": recommended_command, "description": f'{rule["name"]} / {schedule.get("label") or schedule["cron"]}', } ``` ### Technical Analysis The rule name can be taken directly from a quoted portion of a user-controlled natural-language request. The value is subsequently interpolated into a shell command inside double quotes without shell-safe escaping. Double quotes do not neutralize all shell syntax. Command substitutions such as `$()` and backticks are still evaluated by common POSIX shells. Consequently, a rule name such as: ```text "$(touch /tmp/injected)" item every hour ``` can produce a recommended command resembling: ```bash python s ...[truncated 2036 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
SKILL.md:92
Finding

Unpinned Playwright and Browser Dependency Installation

Content
View full analysis
Remediation
View remediation
" python -m playwright install chromium ``` 2. Add a locked dependency file with cryptographic hashes, such as a hash-checked `requirements.txt` generated from a reviewed dependency set. 3. Document the expected Playwright version and corresponding Chromium revision. 4. Use the standard trusted Python package index explicitly where appropriate and avoid unreviewed extra indexes. 5. Perform dependency updates through a controlled review process that includes vulnerability scanning, test execution, and verification of browser artifact changes. 6. Prefer installation in a dedicated virtual environment or container with least privilege rather than installing as an administrator. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • 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 (19)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description describes end-user marketplace search and monitoring behavior. The actual code chunk does not implement any of those capabilities; it only packages the skill files into a distributable archive. This is not merely a supporting helper exposed as the skill behavior—the chunk's primary purpose is build tooling, which materially differs from the declared runtime functionality.

Content

No source excerpt is available for this finding.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/watch_store.py (reported line 18)May include surrounding context.

python
rule.setdefault("action", "watch")
    rule.setdefault("schedule", {"kind": "manual", "label": "수동 또는 상위 스케줄러 연결 필요", "cron": None})
    rule.setdefault("plan_hints", {})
    return rule


def load_state() -> dict[str, Any]:

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/watch_store.py (reported line 64)May include surrounding context.

python
rule.setdefault("action", "watch")
    rule.setdefault("schedule", {"kind": "manual", "label": "수동 또는 상위 스케줄러 연결 필요", "cron": None})
    rule.setdefault("plan_hints", {})
    return rule


def load_state() -> dict[str, Any]:

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/watch_store.py (reported line 113)May include surrounding context.

python
rule.setdefault("action", "watch")
    rule.setdefault("schedule", {"kind": "manual", "label": "수동 또는 상위 스케줄러 연결 필요", "cron": None})
    rule.setdefault("plan_hints", {})
    return rule


def load_state() -> dict[str, Any]:

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/watch_store.py (reported line 120)May include surrounding context.

python
rules = state.get("rules") or []
    for idx, rule in enumerate(rules):
        if rule.get("id") == name_or_id or rule.get("name") == name_or_id:
            return rules.pop(idx)
    return None

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README states that output includes a '사용자 확인용 짧은 한국어 문구', which mandates Korean for user-facing confirmation text. This is a natural-language locale constraint, and the document does not indicate user opt-in, alternative language support, or a region-specific justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The README describes user_confirmation as a short Korean confirmation phrase to show to users. This imposes a specific language in user-facing behavior without presenting choice or documenting a justified locale limitation, which conflicts with the language/locale policy criteria.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill advertises capabilities that imply file read/write and network access, but it does not declare any explicit tool scope or permission boundaries. In an agent environment, that creates an authorization gap: the orchestrator and user cannot easily determine what the skill is allowed to touch, increasing the risk of unintended file modification, persistent state changes, or external requests.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The trigger description is very broad and uses many natural-language examples without clear exclusions or confirmation boundaries. In an agent-routing context, that can cause the skill to activate on ambiguous user requests and perform networked searches or persistent watch-rule operations when the user may have only intended casual discussion or comparison.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The README explicitly encourages interpreting one-line Korean requests directly as watch intents and persisting rules with minimal friction. That increases the chance of unintended state changes, background monitoring, and recurring network activity from ambiguous or casually phrased user input, especially in autonomous or semi-autonomous agent flows.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code is explicitly tied to Korean-language and Korean-market behavior, as shown by use of a Korea-specific price parser and throughout the file's Korean text handling. There is no indication that users can opt into this locale restriction or choose another language/locale.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code renders user-facing text in Korean, beginning with phrases like "중고 매물 브리핑," and the same pattern continues throughout the file. Under the policy, forcing a specific language without user opt-in or a documented justification is a natural-language policy violation.

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 is explicitly specialized for Korean price parsing and formatting, including Korean keywords and output strings such as "가격문의" and "원". Under the policy rule, forcing a specific language or locale without opt-in or documented justification is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The file encodes Korean-specific parsing behavior through parse_price_kr, Korean market synonyms, Korean location hints, and Korean stopwords. This effectively forces a Korean locale/language interpretation for all queries, but the file contains no natural-language indication that the skill is Korea-only or that users can choose another language/locale.

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 detects only Korean trigger phrases such as "감시해줘", "매일", and "가격하락만", and produces Korean-only labels and confirmation text. That enforces a specific language/locale behavior without user opt-in, which matches the language-policy violation criteria.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This code issues HTTP/navigation requests to third-party marketplaces using Playwright, starting with page navigation in the search helpers. There is no visible confirmation prompt, print/log statement, or comment/docstring explaining that the skill will contact external sites and transmit the user's search query.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The parser description states the skill as a Korean used-market search/watch skill in a way that fixes the language/locale context without any visible opt-in or alternative. Under the policy, locale-specific language constraints should either offer a choice or be clearly justified as region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The default schedule label is a natural-language string in Korean ("수동 또는 상위 스케줄러 연결 필요") with no indication that users can choose their preferred language or locale. If this skill is intended for a broader audience, forcing a specific language in user-facing text can violate organizational language/locale policy.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

This line introduces another user-facing default label in Korean only, again without any visible mechanism for locale selection or explicit documentation of a Korean-only scope. Repeated hard-coded locale-specific text increases the likelihood of a policy mismatch for users expecting language neutrality or choice.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.