Back to skill

Security audit

泾川天气预报

Security checks for vulnerabilities and agentic risk

Overview

This is a narrow Jingchuan weather skill that contacts Open-Meteo for forecast data, with a real transport-security weakness but no evidence of data theft, persistence, privilege abuse, or destructive behavior.

Before installing, understand that this skill makes a network request to Open-Meteo and currently accepts unverified or plaintext weather responses; use it only for low-stakes forecast convenience unless the transport handling is fixed.

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/weather.py:25
Finding
Disabled TLS Verification and Plaintext HTTP Downgrade## Vulnerability Details **File Location**: `scripts/weather.py`, lines 25–42 **Vulnerability Type**: Improper certificate validation and insecure protocol fallback **Risk Level**: Medium ### Vulnerable Code ```python # Create a context that does not verify SSL ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5'}) try: resp = urllib.request.urlopen(req, context=ctx, timeout=10) data = json.loads(resp.read().decode('utf-8')) return data except Exception as e: # If SSL fails, try HTTP url_http = url.replace('https://', 'http://') req = urllib.request.Request(url_http, headers={'User-Agent': 'Mozilla/5'}) resp = urllib.request.urlopen(req, timeout=10) data = json.loads(resp.read().decode('utf-8')) return data ``` ### Technical Analysis The script explicitly disables both TLS certificate verification and hostname validation. Consequently, HTTPS encrypts the connection but does not authenticate the Open-Meteo server. An attacker with an on-path network position can present an arbitrary certificate, impersonate the API, and return manipulated weather data. The broad `except Exception` handler further weakens transport security by retrying the request over plaintext HTTP after any exception. This downgrade is not limited to certificate or TLS failures; network errors, response decoding failures, JSON parsing errors, and other runtime exceptions can all trigger it. The fallback request provides neither server authentication nor transport confidentiality or integrity. The API response is also consumed without validating its schema, list lengths, or value types. A forged response could therefore supply misleading values or malformed structures that cause exceptions during report generation. ### Attack Path 1. A user invokes the weather Skill while connected throu ...[truncated 1476 chars]
Remediation
## Remediation Suggestions 1. Preserve Python's default certificate and hostname verification. Remove `ctx.check_hostname = False` and `ctx.verify_mode = ssl.CERT_NONE`, or call `urlopen` without a custom SSL context. 2. Remove the plaintext HTTP fallback entirely. If a verified HTTPS request fails, return a controlled error rather than downgrading transport security. 3. Replace `except Exception` with narrowly scoped handling for expected network, timeout, decoding, and JSON errors. Do not interpret unrelated exceptions as TLS failures. 4. Validate the response before use. Confirm that `daily` is an object, all required fields exist, arrays contain the expected number of entries, and values have appropriate types and ranges. 5. Handle API and validation failures gracefully without exposing stack traces or presenting unverified data as authentic. 6. Keep the existing request timeout and consider limiting response size before JSON parsing to reduce denial-of-service exposure. A secure request pattern would retain verified HTTPS and fail closed: ```python req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5'}) try: with urllib.request.urlopen(req, timeout=10) as resp: data = json.loads(resp.read().decode('utf-8')) except (urllib.error.URLError, TimeoutError, UnicodeDecodeError, json.JSONDecodeError) as exc: raise RuntimeError("Unable to retrieve verified weather data") from exc # Validate the response schema and values before returning it. return data ```
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
Findings (6)

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill describes calling a Python script to fetch weather data from Open-Meteo, which implies network access, but it does not declare any explicit tool scope such as permissions or allowed-tools. Undeclared network capability weakens least-privilege controls and makes it harder for the platform to constrain or audit what external access the skill may use.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The description says the skill auto-triggers on '泾川天气' or similar content, but 'similar content' is undefined and can cause overbroad activation. Ambiguous trigger rules can make the skill run unexpectedly on loosely related user input, increasing the chance of unintended network calls or user confusion.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
Comments, labels, and all formatted output are fixed in Chinese, and the script does not provide any user opt-in or language selection. The policy requires flagging language or locale constraints when a skill forces a specific language without choice or explicit justification.

External Transmission

Medium
Category
Data Exfiltration
Content
import urllib.error
    
    # 天气和日出日落API
    url = f'https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}&daily=weather_code,temperature_2m_max,temperature_2m_min,precipitation_probability_max,sunrise,sunset&timezone=Asia/Shanghai&forecast_days=7'
    
    # 创建不验证SSL的上下文
    ctx = ssl.create_default_context()
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The exception handler catches any error from the HTTPS request and silently retries over plain HTTP, while SSL certificate validation is already disabled for the HTTPS path. This creates a clear transport-security weakness: an attacker on the network can intercept or tamper with the weather response via MITM, and the broad exception handling makes the downgrade trigger far beyond actual SSL failures.

Missing User Warnings

Low
Confidence
88% confidence
Finding
This code fetches weather data from an external API over the network, including a fallback HTTP request, but provides no user-facing print/log message or warning that an outbound request will occur. For code files, network calls that transmit system or user context should have some visible disclosure unless clearly communicated elsewhere.

Static analysis

No suspicious patterns detected.