Back to skill

Security audit

Weather

Security checks for vulnerabilities and agentic risk

Overview

This is a weather skill that makes expected external weather API calls, with some quality and privacy-disclosure issues but no hidden persistence, credential access, destructive behavior, or deceptive payloads found.

Before installing, understand that weather queries, including city names or coordinates, are sent to third-party weather/geocoding services. Prefer the JavaScript CLI entry point over weather.sh, and be aware that multi-city comparison appears broken until the undefined weatherLang bug 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
weather.sh:272
Finding

Plaintext HTTP Requests Expose Location Queries and Weather Responses

Content
View full analysis

Vulnerability Details

File Location: weather.sh, lines 272 and 284
Vulnerability Type: Plaintext transmission of location data and untrusted terminal output
Risk Level: Medium

Complete Vulnerable Code

bash
# Fetch weather data from wttr.in
local weather_data
weather_data=$(curl -s "wttr.in/${city_en}?format=j1" 2>/dev/null) || {
    get_error_message "$lang" "fetch_failed"
    return 1
}

if [[ -z "$weather_data" ]]; then
    get_error_message "$lang" "city_not_found"
    return 1
fi

# For now, use simple format
local result
result=$(curl -s "wttr.in/${city_en}?format=3" 2>/dev/null) || {
    get_error_message "$lang" "fetch_failed"
    return 1
}

The response is subsequently printed without control-character sanitization:

bash
echo "$result"

Technical Analysis

Both curl URLs omit an explicit https:// scheme. Curl consequently treats these as plaintext HTTP requests. The user-supplied location, which may be a city or precise coordinates, is transmitted without transport encryption.

An attacker with an on-path network position can observe the queried location and alter the server response. Because the resulting text is printed directly to the user's terminal, a modified response may contain misleading weather information or terminal control sequences. The location is also interpolated into the URL without explicit URL encoding, reducing request robustness for characters with special URL significance.

Although weather.sh is documented as a reference implementation rather than the primary JavaScript entry point, it is executable and contains a complete main routine, so the vulnerable behavior can be invoked directly.

Attack Path

  1. A user invokes weather.sh with a city name or coordinate pair.
  2. The script places that location in a request to wttr.in over plaintext HTTP.
  3. An attacker capable of observing or modifying the user's network traffic intercepts the request.
  4. The attacker learns the requ ...[truncated 1008 chars]
Remediation
View remediation

Remediation Suggestions

  1. Require HTTPS explicitly for every request:
bash
weather_data=$(curl \
    --fail \
    --silent \
    --show-error \
    --proto '=https' \
    --connect-timeout 5 \
    --max-time 15 \
    "https://wttr.in/${encoded_city}?format=j1")

Apply the same controls to the second request.

  1. URL-encode the location before inserting it into the request path. Prefer a reliable encoding implementation rather than directly interpolating city_en.

  2. Avoid making two requests when one validated JSON response can provide all required data. Parse the HTTPS JSON response locally.

  3. Sanitize externally supplied text before writing it to a terminal. At minimum, remove nonessential C0/C1 control characters and escape sequences.

  4. Do not discard all curl errors with 2>/dev/null; retain safe diagnostic information so TLS and protocol failures are visible.

  5. Consider removing weather.sh from the distributable package if it is only a reference implementation, or clearly prevent its execution and direct users exclusively to the HTTPS-based JavaScript implementation.

Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (32)

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · CONTRIBUTING.md (reported line 144)May include surrounding context.

md
Contributions welcome! Please follow:
- Code style: ESLint + Prettier
- Tests: Vitest
- Documentation: Update SKILL.md and README.md

欢迎贡献!请遵循:
- 代码风格:ESLint + Prettier

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description is for an end-user weather skill with live weather-related capabilities. However, the provided code does not implement weather retrieval, AQI, pollen, alerts, bilingual formatting logic, or city comparison. It merely constructs a static notification object containing a subject and body summarizing project completion and documentation. This is a materially different primary purpose from the declared skill behavior, so it should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description describes a full weather-information skill with multiple end-user features. The provided code does not implement any weather-related functionality at all; it only configures the Jest testing framework. This is a materially different primary purpose, so the description does not accurately represent the supplied code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The code largely matches the declared description: it handles weather lookup, optional AQI/pollen/alerts/advice, Chinese/English language selection, and formatting modes. There are no signs of unrelated or undeclared sensitive capabilities such as file access, credential use, or exfiltration. However, the declared purpose explicitly includes multi-city comparison, and the supplied code's comparison implementation uses lang: weatherLang even though weatherLang is not defined in this snippet. That means the comparison feature, a stated capability, is materially misrepresented because it is likely broken rather than working as described.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The supplied code does align with several declared features: bilingual Chinese/English output, AQI display, pollen display, alert formatting, and multi-city formatting/comparison-style output. However, it does not implement lifestyle suggestions at all, despite the description explicitly claiming that capability. It also does not show any API integration, so the claim about a 'v2.1 completely free API' is unsupported by this chunk. The primary behavior here is limited to presentation/formatting of already-supplied weather objects, rather than a complete weather skill. Therefore the description overstates the implemented functionality in this code segment, producing a material description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The code does implement part of the declared purpose: bilingual weather lookup in Chinese and English for a city query. However, several prominently advertised features are absent. There is no logic for AQI, pollen, warnings/alerts, lifestyle recommendations, or comparing multiple cities. The script only performs a basic single-city weather fetch via wttr.in and simple string translation. This is therefore a description-behavior mismatch because the declared functionality materially exceeds what the code actually does.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This JavaScript file contains natural-language comments and usage examples primarily in Chinese alongside some English labels, which can impose a language expectation on maintainers or users without any opt-in or explanation. The policy explicitly flags language or locale constraints when the skill does not offer choice or clearly justify the limitation.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill metadata declares a runtime dependency on curl and documents use of external weather APIs, but it does not clearly declare tool scope such as allowed shell/network capabilities. Missing explicit permissions weakens least-privilege controls and can let a reviewer or host underestimate what the skill is able to do at runtime.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The code sends user-supplied location data to third-party services (wttr.in and, elsewhere in the file, Open-Meteo geocoding/weather endpoints) without any visible consent gate, minimization step, or user-facing disclosure. Location data can be sensitive personal information, and transmitting it to external providers may expose travel patterns or approximate whereabouts to those providers and any logs along the path.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

The file is designed to transmit latitude/longitude and weather queries to an external API endpoint at api.open-meteo.com. In this skill context that behavior is functionally necessary, but it still constitutes a real privacy/security concern because user location data leaves the local trust boundary and may be retained or correlated by third parties.

Content

Scanner excerpt · lib/api.js (reported line 73)May include surrounding context.

js
}

// ==================== Open-Meteo API ====================
const OPENMETEO_API = 'https://api.open-meteo.com/v1';

class OpenMeteoAPI {
  constructor() {

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

This alerts feature also sends user coordinates to an external Open-Meteo endpoint, extending third-party exposure beyond core weather lookup. In a weather skill this is expected behavior, but it remains sensitive because alert lookups can reveal a user's approximate location without any in-file privacy control or opt-in.

Content

Scanner excerpt · lib/api.js (reported line 365)May include surrounding context.

js
}

// ==================== Open-Meteo Weather Alerts API (Free) ====================
const OPENMETEO_ALERTS_API = 'https://api.open-meteo.com/v1/alerts';

class OpenMeteoAlertsAPI {
  constructor() {

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This test file contains multiple natural-language locale selections that explicitly call suggestion generation with 'zh', and later formats output with lang: 'zh'. That indicates the skill behavior may force Chinese-language output in at least some flows without any visible user opt-in or documented locale choice, which matches the language/locale policy violation category.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The workflow test requests all suggestions in 'zh' and formats final output with lang: 'zh', then asserts Chinese text is present. In the absence of any visible user-consent or locale-selection mechanism in this file, this suggests the skill may impose a specific language in normal operation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

SQP-3 applies to all file types and covers natural-language locale policy issues. The phrase 'Bilingual Support - Chinese/English' presents language support as fixed rather than user-selectable, and this file does not indicate any opt-in or language choice mechanism.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README encourages users to submit city names, airport codes, and exact coordinates to external weather providers without disclosing that this user-supplied location data is transmitted to third-party services. While expected for a weather skill, the lack of transparency creates a privacy risk, especially for precise coordinates or sensitive travel/location queries.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The documentation says 'No API key required for most features,' which implies some features may differ, but elsewhere it repeatedly presents the overall skill as '完全免费 API' and '无需 API Key'. In the same README, WAQI is listed as an API source for AQI, which contradicts the blanket no-key messaging because WAQI access is commonly token-based.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill encourages users to submit city names, airports, and exact coordinates, and it states that automatic geocoding plus third-party weather services are used. Without a privacy notice, users may unknowingly send location data to external providers, which can expose sensitive travel patterns or approximate whereabouts.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The thrown error message is hard-coded in Chinese, which imposes a specific language regardless of user preference or configured locale. This is a natural-language policy issue because the file otherwise supports language selection in places, but these user-visible errors do not offer opt-in or localization choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

This user-visible error is also hard-coded in Chinese, overriding any user locale expectations. Since the file includes language-related options such as lang, hard-coded Chinese output is inconsistent and may violate language-choice policy.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The validation error shown when too few cities are provided is hard-coded in Chinese and does not respect user language preference. This is a direct language/locale policy issue because it presents mandatory Chinese output without opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The documented language parameter restricts output to 'zh/en/auto', and later output strings are hard-coded to Chinese-versus-English branches. This creates a locale policy concern because the skill supports only a forced binary language choice rather than offering open user locale selection or clearly documenting a justified regional limitation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The formatter defaults lang to auto and then derives the output language from the location string, which can cause the skill to force English or Chinese without an explicit user choice. This matches the policy concern about locale/language being imposed without opt-in rather than offered as a user-controlled preference.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

In formatMultiple, the code again defaults to lang = 'auto' and selects translations based on detected characters in the location field. This can override user expectations about output locale and represents the same natural-language policy issue in another entry point.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The table formatter also uses lang = 'auto' and chooses a locale by inspecting the location text. Because this behavior is automatic rather than user-selected, it can violate language/locale policy expectations across this output mode as well.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill infers output language by checking whether the location contains Chinese characters and defaults to English otherwise. This imposes a locale choice based on heuristics rather than an explicit user preference, which can violate language/locale policy expectations requiring user choice or opt-in.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.