Back to skill

Security audit

MeteoSwiss Open Data

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly fetches public Swiss weather data, but it also recommends adding a persistent third-party MCP server that is not verified or clearly scoped.

Use the bundled scripts or direct `data.geo.admin.ch` URLs for normal weather lookups. Do not add the suggested `meteoswiss-mcp.ars.is` MCP server unless you intentionally trust that third-party service and understand it can add remote tools to your agent environment.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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)

T07 · Tool Hijacking and Spoofing

Warning
Location
SKILL.md:113
Finding

Registration of an Unverified Third-Party MCP Server

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 113-115
Vulnerability Type: Unverified external tool provider registration
Risk Level: Medium

Vulnerable Code

markdown
## MCP Server Alternative

For complex queries (fuzzy search, geocoding, structured JSON), use the MCP server: `claude mcp add meteoswiss https://meteoswiss-mcp.ars.is/mcp`

Technical Analysis

The skill recommends registering an MCP server hosted on the non-official domain meteoswiss-mcp.ars.is. The audited project does not contain the server implementation, a pinned version, integrity metadata, or another mechanism through which the behavior of this external component can be verified.

An MCP server can supply tool definitions and tool results to an agent. Consequently, the effective behavior exposed by this endpoint may change after the skill has been reviewed. If the server or its hosting infrastructure is compromised, it could provide misleading tool descriptions, malicious response content, or unexpected capabilities under names that appear related to MeteoSwiss.

The instruction does not itself prove that the referenced server is malicious. The security issue is the unverified extension of the agent's tool trust boundary to a mutable third-party service.

Attack Path

  1. An agent or user follows the recommendation in SKILL.md.
  2. The command registers the third-party MCP endpoint.
  3. The endpoint is subsequently compromised, transferred, or modified by its operator.
  4. The server returns attacker-controlled tool definitions or results.
  5. The agent treats those tools and responses as trusted MeteoSwiss functionality.
  6. Attacker-controlled content may then influence subsequent agent decisions or tool calls, subject to the permissions and confirmation controls of the MCP client.

Impact Assessment

The endpoint could influence operations performed through the registered MCP tools and the agent's interpretation of returned data. The practical ...[truncated 298 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove the MCP registration recommendation when direct access to the official MeteoSwiss data source is sufficient.
  2. Prefer an official MeteoSwiss endpoint or a server whose implementation and deployment process can be independently audited.
  3. Require explicit, informed user approval before registering any third-party MCP server.
  4. Clearly document that the endpoint is operated by a third party and lies outside the audited package's trust boundary.
  5. Pin the server to a verifiable implementation or deployment identity where the client ecosystem supports this.
  6. Restrict enabled MCP tools to the minimum required set and require confirmation for sensitive operations.
  7. Periodically review the registered server's tool definitions and operator ownership for unexpected changes.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/forecast.sh:54
Finding

STAC Asset URLs Are Fetched Without Scheme or Origin Validation

Content
View full analysis

Vulnerability Details

File Locations: scripts/forecast.sh, lines 54-62; scripts/search-forecast-points.sh, lines 34-38
Vulnerability Type: Unvalidated server-supplied URL fetch
Risk Level: Low

Vulnerable Code

scripts/forecast.sh, lines 54-62:

bash
  ASSET_URL=$(echo "$ITEM_JSON" \
    | jq -r "[.assets | to_entries[] | select(.key | contains(\"$PARAM\"))] | sort_by(.key) | last | .value.href // empty")

  if [[ -z "$ASSET_URL" ]]; then
    echo "$PARAM=no_data"
    continue
  fi

  curl -sf "$ASSET_URL" \

scripts/search-forecast-points.sh, lines 34-38:

bash
META_URL=$(curl -sf "$STAC_URL" \
  | jq -r '[.assets | to_entries[] | select(.key | contains("meta_point")) | .value.href] | first') \
  || { echo "Error: failed to fetch STAC collection" >&2; exit 1; }

curl -sf "$META_URL" \

Technical Analysis

Both scripts extract an asset URL from a remote STAC response and pass it directly to curl. They do not verify that the resulting URL:

  • Uses HTTPS.
  • Belongs to the expected data.geo.admin.ch host.
  • Uses an explicitly permitted port.
  • Avoids loopback, link-local, or private network destinations after DNS resolution and redirects.

This creates a server-side request forgery-like trust-boundary issue. If an attacker can alter the STAC response or compromise the upstream service, the scripts can be induced to issue a GET request to an attacker-selected destination from the machine running the skill.

The downloaded responses are passed to data-processing tools rather than executed as code. This materially limits the impact: the reviewed flow does not provide a direct remote-code-execution path. In addition, exploitation requires control over or compromise of the trusted HTTPS response path.

Attack Path

  1. An attacker compromises the STAC service, its content-production path, or another trusted component capable of changing the returned JSON.
  2. The attacker replaces an asset href with a URL targeting an ...[truncated 1030 chars]
Remediation
View remediation

Remediation Suggestions

  1. Parse every STAC-provided URL before passing it to curl.
  2. Require the exact https scheme.
  3. Enforce an explicit hostname allowlist, preferably only data.geo.admin.ch unless additional documented official hosts are required.
  4. Reject embedded credentials, nonstandard ports, malformed URLs, and unexpected schemes.
  5. Disable redirects with --max-redirs 0, or validate every redirect destination before following it.
  6. Where the runtime permits, resolve the host and reject loopback, link-local, private, multicast, and otherwise reserved address ranges.
  7. Apply connection and total request timeouts and retain response-size limits to reduce exposure to malicious or defective endpoints.
  8. Fail closed when jq returns null, a non-URL value, or a URL outside the allowlist.
  9. Apply the same validation helper consistently to both ASSET_URL in forecast.sh and META_URL in search-forecast-points.sh.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (20)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill explicitly instructs the agent to use shell commands (curl, awk, jq, iconv) but does not declare any permissions or allowed-tools scope. That creates an authorization ambiguity where an agent may execute shell/network actions without an explicit least-privilege contract, increasing the chance of unintended command execution or policy bypass in tool-enabled environments.

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 · README.md (reported line 31)May include surrounding context.

md
fi

ABBR=$(echo "$STATION" | tr '[:upper:]' '[:lower:]')
URL="https://data.geo.admin.ch/ch.meteoschweiz.ogd-pollen/${ABBR}/ogd-pollen_${ABBR}_d_now.csv"

DATA=$(curl -sf "$URL" | iconv -f latin1 -t utf-8) || {
  echo "Error: failed to fetch pollen data for '$STATION'" >&2

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 · README.md (reported line 32)May include surrounding context.

md
fi

ABBR=$(echo "$STATION" | tr '[:upper:]' '[:lower:]')
URL="https://data.geo.admin.ch/ch.meteoschweiz.ogd-pollen/${ABBR}/ogd-pollen_${ABBR}_d_now.csv"

DATA=$(curl -sf "$URL" | iconv -f latin1 -t utf-8) || {
  echo "Error: failed to fetch pollen data for '$STATION'" >&2

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 · README.md (reported line 33)May include surrounding context.

md
fi

ABBR=$(echo "$STATION" | tr '[:upper:]' '[:lower:]')
URL="https://data.geo.admin.ch/ch.meteoschweiz.ogd-pollen/${ABBR}/ogd-pollen_${ABBR}_d_now.csv"

DATA=$(curl -sf "$URL" | iconv -f latin1 -t utf-8) || {
  echo "Error: failed to fetch pollen data for '$STATION'" >&2

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 · REFERENCE.md (reported line 194)May include surrounding context.

md
fi

ABBR=$(echo "$STATION" | tr '[:upper:]' '[:lower:]')
URL="https://data.geo.admin.ch/ch.meteoschweiz.ogd-pollen/${ABBR}/ogd-pollen_${ABBR}_d_now.csv"

DATA=$(curl -sf "$URL" | iconv -f latin1 -t utf-8) || {
  echo "Error: failed to fetch pollen data for '$STATION'" >&2

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 · REFERENCE.md (reported line 198)May include surrounding context.

md
fi

ABBR=$(echo "$STATION" | tr '[:upper:]' '[:lower:]')
URL="https://data.geo.admin.ch/ch.meteoschweiz.ogd-pollen/${ABBR}/ogd-pollen_${ABBR}_d_now.csv"

DATA=$(curl -sf "$URL" | iconv -f latin1 -t utf-8) || {
  echo "Error: failed to fetch pollen data for '$STATION'" >&2

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 · SKILL.md (reported line 24)May include surrounding context.

md
fi

ABBR=$(echo "$STATION" | tr '[:upper:]' '[:lower:]')
URL="https://data.geo.admin.ch/ch.meteoschweiz.ogd-pollen/${ABBR}/ogd-pollen_${ABBR}_d_now.csv"

DATA=$(curl -sf "$URL" | iconv -f latin1 -t utf-8) || {
  echo "Error: failed to fetch pollen data for '$STATION'" >&2

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 · SKILL.md (reported line 28)May include surrounding context.

md
fi

ABBR=$(echo "$STATION" | tr '[:upper:]' '[:lower:]')
URL="https://data.geo.admin.ch/ch.meteoschweiz.ogd-pollen/${ABBR}/ogd-pollen_${ABBR}_d_now.csv"

DATA=$(curl -sf "$URL" | iconv -f latin1 -t utf-8) || {
  echo "Error: failed to fetch pollen data for '$STATION'" >&2

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 · SKILL.md (reported line 30)May include surrounding context.

md
fi

ABBR=$(echo "$STATION" | tr '[:upper:]' '[:lower:]')
URL="https://data.geo.admin.ch/ch.meteoschweiz.ogd-pollen/${ABBR}/ogd-pollen_${ABBR}_d_now.csv"

DATA=$(curl -sf "$URL" | iconv -f latin1 -t utf-8) || {
  echo "Error: failed to fetch pollen data for '$STATION'" >&2

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 · SKILL.md (reported line 37)May include surrounding context.

md
fi

ABBR=$(echo "$STATION" | tr '[:upper:]' '[:lower:]')
URL="https://data.geo.admin.ch/ch.meteoschweiz.ogd-pollen/${ABBR}/ogd-pollen_${ABBR}_d_now.csv"

DATA=$(curl -sf "$URL" | iconv -f latin1 -t utf-8) || {
  echo "Error: failed to fetch pollen data for '$STATION'" >&2

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 · SKILL.md (reported line 47)May include surrounding context.

md
fi

ABBR=$(echo "$STATION" | tr '[:upper:]' '[:lower:]')
URL="https://data.geo.admin.ch/ch.meteoschweiz.ogd-pollen/${ABBR}/ogd-pollen_${ABBR}_d_now.csv"

DATA=$(curl -sf "$URL" | iconv -f latin1 -t utf-8) || {
  echo "Error: failed to fetch pollen data for '$STATION'" >&2

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 · SKILL.md (reported line 57)May include surrounding context.

md
fi

ABBR=$(echo "$STATION" | tr '[:upper:]' '[:lower:]')
URL="https://data.geo.admin.ch/ch.meteoschweiz.ogd-pollen/${ABBR}/ogd-pollen_${ABBR}_d_now.csv"

DATA=$(curl -sf "$URL" | iconv -f latin1 -t utf-8) || {
  echo "Error: failed to fetch pollen data for '$STATION'" >&2

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 · SKILL.md (reported line 71)May include surrounding context.

md
fi

ABBR=$(echo "$STATION" | tr '[:upper:]' '[:lower:]')
URL="https://data.geo.admin.ch/ch.meteoschweiz.ogd-pollen/${ABBR}/ogd-pollen_${ABBR}_d_now.csv"

DATA=$(curl -sf "$URL" | iconv -f latin1 -t utf-8) || {
  echo "Error: failed to fetch pollen data for '$STATION'" >&2

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 · SKILL.md (reported line 75)May include surrounding context.

md
fi

ABBR=$(echo "$STATION" | tr '[:upper:]' '[:lower:]')
URL="https://data.geo.admin.ch/ch.meteoschweiz.ogd-pollen/${ABBR}/ogd-pollen_${ABBR}_d_now.csv"

DATA=$(curl -sf "$URL" | iconv -f latin1 -t utf-8) || {
  echo "Error: failed to fetch pollen data for '$STATION'" >&2

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 · SKILL.md (reported line 87)May include surrounding context.

md
fi

ABBR=$(echo "$STATION" | tr '[:upper:]' '[:lower:]')
URL="https://data.geo.admin.ch/ch.meteoschweiz.ogd-pollen/${ABBR}/ogd-pollen_${ABBR}_d_now.csv"

DATA=$(curl -sf "$URL" | iconv -f latin1 -t utf-8) || {
  echo "Error: failed to fetch pollen data for '$STATION'" >&2

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/current-weather.sh (reported line 30)May include surrounding context.

sh
fi

ABBR=$(echo "$STATION" | tr '[:upper:]' '[:lower:]')
URL="https://data.geo.admin.ch/ch.meteoschweiz.ogd-pollen/${ABBR}/ogd-pollen_${ABBR}_d_now.csv"

DATA=$(curl -sf "$URL" | iconv -f latin1 -t utf-8) || {
  echo "Error: failed to fetch pollen data for '$STATION'" >&2

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/forecast.sh (reported line 30)May include surrounding context.

sh
fi

ABBR=$(echo "$STATION" | tr '[:upper:]' '[:lower:]')
URL="https://data.geo.admin.ch/ch.meteoschweiz.ogd-pollen/${ABBR}/ogd-pollen_${ABBR}_d_now.csv"

DATA=$(curl -sf "$URL" | iconv -f latin1 -t utf-8) || {
  echo "Error: failed to fetch pollen data for '$STATION'" >&2

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/pollen.sh (reported line 29)May include surrounding context.

sh
fi

ABBR=$(echo "$STATION" | tr '[:upper:]' '[:lower:]')
URL="https://data.geo.admin.ch/ch.meteoschweiz.ogd-pollen/${ABBR}/ogd-pollen_${ABBR}_d_now.csv"

DATA=$(curl -sf "$URL" | iconv -f latin1 -t utf-8) || {
  echo "Error: failed to fetch pollen data for '$STATION'" >&2

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/search-forecast-points.sh (reported line 31)May include surrounding context.

sh
fi

ABBR=$(echo "$STATION" | tr '[:upper:]' '[:lower:]')
URL="https://data.geo.admin.ch/ch.meteoschweiz.ogd-pollen/${ABBR}/ogd-pollen_${ABBR}_d_now.csv"

DATA=$(curl -sf "$URL" | iconv -f latin1 -t utf-8) || {
  echo "Error: failed to fetch pollen data for '$STATION'" >&2

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/search-stations.sh (reported line 30)May include surrounding context.

sh
fi

ABBR=$(echo "$STATION" | tr '[:upper:]' '[:lower:]')
URL="https://data.geo.admin.ch/ch.meteoschweiz.ogd-pollen/${ABBR}/ogd-pollen_${ABBR}_d_now.csv"

DATA=$(curl -sf "$URL" | iconv -f latin1 -t utf-8) || {
  echo "Error: failed to fetch pollen data for '$STATION'" >&2