Back to skill

Security audit

Weather 2.0

Security checks for vulnerabilities and agentic risk

Overview

This weather skill uses disclosed public weather services to answer forecast requests and does not show hidden local access, persistence, or credential handling.

Install only if you are comfortable with location names being sent to wttr.in and, when fallback is needed, Open-Meteo. Prefer HTTPS examples for wttr.in requests to avoid plaintext transport exposure.

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
SKILL.md:28
Finding

Weather Requests May Use Unencrypted HTTP Transport

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 28–31
Vulnerability Type: Plaintext network communication
Risk Level: Low

Vulnerable Code

sh
curl -s "wttr.in/London?2&m"
curl -s "wttr.in/London?T&m"
curl -s "wttr.in/London?format=3"
curl -s "wttr.in/London?format=%l:+%c+%t+%h+%w"

Technical Analysis

These command examples omit the https:// scheme. As a result, curl may initiate a plaintext HTTP request rather than enforcing TLS from the beginning. Even if the service normally redirects HTTP requests to HTTPS, the initial request and redirect response remain exposed to an on-path attacker.

The queried place is incorporated into the URL path, so the initial request can disclose location information. An attacker controlling or observing the network could read the query, modify the response, or replace the redirect destination. Because the Skill treats the returned body as weather information, manipulated content could be summarized and presented as legitimate forecast data.

External weather access is necessary for the declared functionality, and no transmission of credentials, local files, environment variables, memory, or unrelated system data was identified. The issue is limited to the transport security of the scheme-less examples.

Attack Path

  1. A user requests weather information for a named location.
  2. The Agent follows one of the documented scheme-less curl examples and substitutes the requested place into the URL.
  3. curl initiates a plaintext HTTP connection to wttr.in.
  4. An on-path attacker observes the requested location or intercepts the connection.
  5. The attacker may alter the weather response or redirect the request to an attacker-controlled destination.
  6. The Agent interprets the manipulated body as forecast data and may present it to the user.

Impact Assessment

Exploitation requires network-path visibility or control. A successful attack ...[truncated 374 chars]

Remediation
View remediation

Remediation Suggestions

Replace every scheme-less endpoint with an explicit HTTPS URL and require HTTPS at the client level:

sh
curl --fail --silent --show-error --proto '=https' \
  "https://wttr.in/London?2&m"

Apply the same change to the full-table, current-weather, and custom-format examples. Additional hardening should include:

  • Permit only the documented wttr.in, geocoding-api.open-meteo.com, and api.open-meteo.com HTTPS hosts.
  • Do not follow redirects to non-HTTPS URLs or unapproved hosts.
  • URL-encode user-provided place names rather than directly interpolating arbitrary text.
  • Preserve TLS certificate verification and do not introduce curl -k or --insecure.
  • Retain the existing one-request default and restricted fallback flow to minimize disclosure of location data.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (3)

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · SKILL.md (reported line 45)May include surrounding context.

md
**MANDATORY for skill:weather:** **One fetch first:** prefer `https://wttr.in/PLACE?2&m` for tomorrow/today-style questions — smaller/faster than the full table. Use `https://wttr.in/PLACE?T&m` only if the user wants a longer range or `?2` is insufficient. If the body is a normal forecast, **answer and stop** — do not call Open-Meteo in the same run. **Open-Meteo** only if wttr fails or raw JSON is needed: (1) `https://geocoding-api.open-meteo.com/v1/search?name=…&count=10`; (2) if `results` is missing or empty, **one** retry with shorter `name` + `countryCode` (e.g. `https://geocoding-api.open-meteo.com/v1/search?name=Breitenau&countryCode=AT&count=10` for “Breitenau am Hochlantsch”) and pick the row whose `admin3`/`admin2`/`admin1` matches the user phrase; (3) `https://api.open-meteo.com/v1/forecast?latitude=…&longitude=…&daily=temperature_2m_max,temperature_2m_min,precipitation_probability_max,weathercode&forecast_days=7&timezone=auto`. Never claim the place was not found after a single geocode on compound EU names. Reply per **How to answer**: plain language; no coordinates or WMO codes unless the user asked for technical detail.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · SKILL.md (reported line 47)May include surrounding context.

md
**MANDATORY for skill:weather:** **One fetch first:** prefer `https://wttr.in/PLACE?2&m` for tomorrow/today-style questions — smaller/faster than the full table. Use `https://wttr.in/PLACE?T&m` only if the user wants a longer range or `?2` is insufficient. If the body is a normal forecast, **answer and stop** — do not call Open-Meteo in the same run. **Open-Meteo** only if wttr fails or raw JSON is needed: (1) `https://geocoding-api.open-meteo.com/v1/search?name=…&count=10`; (2) if `results` is missing or empty, **one** retry with shorter `name` + `countryCode` (e.g. `https://geocoding-api.open-meteo.com/v1/search?name=Breitenau&countryCode=AT&count=10` for “Breitenau am Hochlantsch”) and pick the row whose `admin3`/`admin2`/`admin1` matches the user phrase; (3) `https://api.open-meteo.com/v1/forecast?latitude=…&longitude=…&daily=temperature_2m_max,temperature_2m_min,precipitation_probability_max,weathercode&forecast_days=7&timezone=auto`. Never claim the place was not found after a single geocode on compound EU names. Reply per **How to answer**: plain language; no coordinates or WMO codes unless the user asked for technical detail.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · mandatory.md (reported line 1)May include surrounding context.

md
**MANDATORY for skill:weather:** **One fetch first:** prefer `https://wttr.in/PLACE?2&m` for tomorrow/today-style questions — smaller/faster than the full table. Use `https://wttr.in/PLACE?T&m` only if the user wants a longer range or `?2` is insufficient. If the body is a normal forecast, **answer and stop** — do not call Open-Meteo in the same run. **Open-Meteo** only if wttr fails or raw JSON is needed: (1) `https://geocoding-api.open-meteo.com/v1/search?name=…&count=10`; (2) if `results` is missing or empty, **one** retry with shorter `name` + `countryCode` (e.g. `https://geocoding-api.open-meteo.com/v1/search?name=Breitenau&countryCode=AT&count=10` for “Breitenau am Hochlantsch”) and pick the row whose `admin3`/`admin2`/`admin1` matches the user phrase; (3) `https://api.open-meteo.com/v1/forecast?latitude=…&longitude=…&daily=temperature_2m_max,temperature_2m_min,precipitation_probability_max,weathercode&forecast_days=7&timezone=auto`. Never claim the place was not found after a single geocode on compound EU names. Reply per **How to answer**: plain language; no coordinates or WMO codes unless the user asked for technical detail.

Static analysis

No suspicious patterns detected.