Back to skill

Security audit

钓鱼热点推送

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does its stated fishing-hotspot job, but it needs review because it automatically reuses another skill's API keys and saves generated HTML reports without safely escaping outside data.

Install only if you are comfortable sharing fishing-related city/location queries and extracted place names with Amap and QWeather, and with this skill reading API keys from an existing fishing-trip-planner config. Treat generated HTML reports as untrusted local files until the report renderer escapes dynamic values and restricts output paths.

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/hotspot_push.py:672
Finding

Stored HTML Injection in Generated Fishing Reports

Content
View full analysis
{date[-5:] if len(date)>=10 else date}
{emoji}
{text_day}
{temp_low}° / {temp_high}°
🌬️ {wind}级
""" if fishing_index: fi_cat = fishing_index.get("category", "?") fi_text = fishing_index.get("text", "") fi_level = fishing_index.get("level", "2") fi_colors = {"1": "#22c55e", "2": "#3b82f6", "3": "#f59e0b", "4": "#ef4444"} fi_color = fi_colors.get(fi_level, "#94a3b8") fi_html = f"""
{fi_cat} {fi_text}
""" hotspot_cards = "" if hotspots: for i, h in enumerate(hotspots[:10]): rank_emoji = ["🥇", "🥈", "🥉", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣", "🔟"][i] species_tags = "" for s in h.get("fish_species", [])[:4]: species_tags += f'🐟 {s}' bait_tags = "" for b in h.get("bait", [])[:3]: bait_tags += f'🪱 {b}' dist_km = h.get("distance_km") dist_str = f"{dist_km}km" if dist_km else "距离未知" sent_map = {"positive": "🟢", "negative": "🔴", "neutral": "🟡"} sent_emoji = sent_map.get(h.get("sentiment", "neutral"), "🟡") score = h.get("score", 50) score_color = h.get("level_color", "#3b82f6") social_badge = "" if h.get("source") == "social": mention = h.get("mention_co ...[truncated 4283 chars]
Remediation
View remediation
str: return escape(str(value), quote=True) ``` Apply this function to the city, display name, POI name, weather fields, fishing-index text, hotspot location, and every other externally sourced value. 2. Construct the Amap navigation URL with URL-encoding rather than string concatenation: ```python from urllib.parse import urlencode from html import escape query = urlencode({ "to": f"{longitude},{latitude},{location_name}" }) navigation_url = escape( f"https://uri.amap.com/navigation?{query}", quote=True, ) ``` 3. Validate values before rendering: - Parse longitude and latitude as finite floating-point values and enforce valid geographic ranges. - Parse scores and widths as bounded integers. - Restrict colors and status values to internal allowlists. - Reject unexpected control characters in externally supplied text. 4. Add a restrictive Content Security Policy to generated reports, for example: ```html ``` If external navigation must remain available, permit only the required navigation behavior without enabling scripts or unrestricted resource loading. 5. Add `rel="noopener noreferrer"` to links opened with `target="_blank"`. 6. Add automated tests that generate reports using payloads in every dynamic field, including: ```html "> javascript:alert(1) ``` The tests should verify that these values appear only as encoded text and never create executable elements, event-handler attributes, or attacker-controlled URL schemes. ]]>
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
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (21)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README states that this skill will automatically reuse API keys from another skill, but it does not clearly warn the user that credentials configured for one tool will be accessed by another. Cross-skill credential reuse weakens isolation and can lead to unintended secret exposure or broader compromise if either skill is unsafe or misconfigured.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
79% confidence
Finding

The README indicates that social text is supplied via agent web search and analyzed, but it does not clearly disclose what data may be transmitted to external APIs or services during processing. When combined with user location and fishing activity, this can create a privacy risk because users may not realize third-party services could receive contextual or behavioral data.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill advertises behavior that uses environment secrets, local file read/write, network access, and shell execution, but it does not declare any explicit tool scope or permission boundaries. This increases the chance of over-privileged execution and makes it harder for a host agent or reviewer to constrain what the skill is allowed to do.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The trigger list includes broad phrases such as '附近钓点', '哪里出鱼', and similar everyday wording that may appear in normal conversation, causing unintended activation. Accidental invocation can expose user location, initiate web searches, and generate persistent reports without the user clearly intending to run the skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill describes collecting user location, sending search text and query-derived content to external services, and combining this with weather and map APIs, but it does not clearly warn the user that third parties will receive this data. This creates a privacy risk because location and potentially sensitive user-provided text can be transmitted off-device without informed consent.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The When-to-Use section repeats ambiguous activation guidance without constraints, confirmation requirements, or disambiguation rules. In context, this matters because the workflow can perform searches, call third-party APIs, and archive outputs, so accidental activation has privacy and side-effect risks.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The module docstring and CLI usage examples are entirely Chinese-facing, and the rest of the script continues with Chinese prompts, logs, and generated HTML. For a general-purpose skill, this constitutes a language/locale policy issue because users are not given any opt-in or alternative language selection.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill reads API keys and user_name from another skill's private config file under ~/.fishing-planner without explicit consent or isolation boundaries. This creates cross-skill data access and weakens least-privilege guarantees, allowing one skill to consume secrets and personal data collected for a different purpose.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/hotspot_push.py (reported line 40)May include surrounding context.

python
FISHING_PLANNER_CONFIG = Path.home() / ".fishing-planner" / "config.json"

AMAP_BASE = "https://restapi.amap.com/v3"
QWEATHER_BASE = "https://api.qweather.com/v7"
QWEATHER_GEO = "https://geoapi.qweather.com/v2"

# ─── 钓鱼领域知识库 ──────────────────────────────────────────

Tainted flow: 'params' from input (line 342, user input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/hotspot_push.py (reported line 297)May include surrounding context.

python
if city:
        params["city"] = city
    try:
        resp = requests.get(f"{AMAP_BASE}/geocode/geo", params=params, timeout=10)
        data = resp.json()
        if data.get("status") == "1" and data.get("geocodes"):
            gc = data["geocodes"][0]

Tainted flow: 'params' from input (line 342, user input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/hotspot_push.py (reported line 329)May include surrounding context.

python
params["types"] = types

    try:
        resp = requests.get(f"{AMAP_BASE}/place/text", params=params, timeout=10)
        data = resp.json()
        if data.get("status") == "1":
            return data.get("pois", [])

Tainted flow: 'params' from input (line 342, user input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/hotspot_push.py (reported line 351)May include surrounding context.

python
"extensions": "all",
    }
    try:
        resp = requests.get(f"{AMAP_BASE}/place/around", params=params, timeout=10)
        data = resp.json()
        if data.get("status") == "1":
            return data.get("pois", [])

Tainted flow: 'params' from input (line 342, user input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/hotspot_push.py (reported line 370)May include surrounding context.

python
if key:
        params["key"] = key
    try:
        resp = requests.get(f"{QWEATHER_GEO}/city/lookup", params=params, timeout=10)
        data = resp.json()
        if data.get("code") == "200" and data.get("location"):
            loc = data["location"][0]

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script transmits user-provided city/location data to third-party map and weather providers during normal operation without an explicit warning or consent step. In this skill's context, location is sensitive personal information, so undisclosed external transmission materially increases privacy risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Externally supplied text intelligence is parsed for place names and then geocoded through a third-party API without warning that sensitive location details from that text may be transmitted. Because the input may contain personal, private, or third-party location information, this can unintentionally exfiltrate sensitive context beyond the user's expectations.

Content

No source excerpt is available for this finding.

Tainted flow: 'output_path' from input (line 1372, user input) → open (file write)

Medium
Category
Data Flow
Confidence
95% confidence
Finding

The script writes HTML to an arbitrary path provided via --output with no directory restriction or safety checks. If this skill runs with elevated privileges or in an automation context, a user or upstream agent could overwrite sensitive files, clobber application data, or place HTML in unintended web-served locations.

Content

Scanner excerpt · scripts/hotspot_push.py (reported line 1368)May include surrounding context.

python
if args.output:
            output_path = os.path.abspath(args.output)
            with open(output_path, "w", encoding="utf-8") as f:
                f.write(html)
            log(f"报告已保存: {output_path}", "OK")
        else:

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README presents the skill description entirely in Chinese, which can effectively force a specific language for users without indicating any opt-in or locale limitation. Under the language/locale policy, this is a natural-language constraint that should either be optional or explicitly justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The skill documentation and operational examples are presented entirely in Chinese, and the trigger phrases and outputs are implied to be Chinese-centric, without stating that users may choose another language. This can constitute a language/locale policy issue when no opt-in or alternative is offered.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The skill states that HTML reports and push history are automatically archived locally, but it does not prominently warn users about retention of location-linked fishing activity and extracted text. Persistent local storage can expose sensitive behavior patterns to other local users, backups, or later compromise of the machine.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

This markdown file contains only Chinese-language instructions and does not indicate that the user can choose another language or that the skill is intended solely for a Chinese-speaking or region-specific audience. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The generated report footer and info bar state the data source as only '和风天气 + 高德地图' and '和风天气 · 高德地图', but the code also incorporates externally supplied social-media/search text via NLP when provided. This is not merely incomplete formatting: the report actively attributes the report to a narrower set of sources than the code actually uses.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.