Back to skill

Security audit

xiaomi-weather

Security checks for vulnerabilities and agentic risk

Overview

This skill is a straightforward Xiaomi weather lookup tool with some transparency and temporary-file safety caveats, but no evidence of deception, exfiltration, privilege escalation, or destructive intent.

Reasonable to install if you are comfortable with a China-focused weather tool making external requests to Xiaomi and, for unknown city names, a GitHub-hosted city-code database. Avoid running it as root, and prefer a future version that uses a user-private cache directory, pins or verifies the city database, and clearly documents the external lookup privacy implications.

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/xiaomi-weather.sh:48
Finding

Predictable Shared Temporary File Permits Symlink Overwrite and Cache Poisoning

Content
View full analysis

Vulnerability Details

File Location: scripts/xiaomi-weather.sh, lines 48–57
Vulnerability Type: Unsafe temporary-file handling
Risk Level: Medium

Vulnerable Code

bash
lookup_city() {
  local name="$1"
  local code="${CITIES[$name]:-}"
  [ -n "$code" ] && { echo "$code"; return 0; }
  # 尝试按名称模糊匹配远程库(需要 curl 联网)
  local db="/tmp/xiaomi_weather_cities.tsv"
  if [ ! -f "$db" ]; then
    curl -fsSL --max-time 15 \
      "https://raw.githubusercontent.com/huanghui0906/API/master/xiaomi_weather.db" \
      -o "$db" 2>/dev/null || return 1
  fi
  # 数据库格式含 city_name / city_num,做一次简单 grep

Technical Analysis

The script stores remotely retrieved data at the fixed, globally predictable path /tmp/xiaomi_weather_cities.tsv. It neither creates this file securely nor verifies its type, owner, permissions, or integrity before trusting it.

The [ ! -f "$db" ] check and subsequent curl -o "$db" operation are also separate filesystem operations, creating a time-of-check-to-time-of-use race. An attacker with access to the shared temporary directory can manipulate the path between those operations.

Two practical exploitation modes exist:

  1. Symlink-based file overwrite: An attacker places or races a symbolic link at the predictable path. When curl writes its response, the target file may be overwritten with the privileges of the user running the Skill.
  2. City-database poisoning: An attacker creates a regular file at that path before execution. Because the script only checks whether it is a regular file, it accepts attacker-controlled contents and extracts a nine-digit location code from them.

The downloaded resource additionally follows the mutable master branch and is not authenticated with a pinned commit or checksum. HTTPS protects data in transit but does not guarantee that the repository content remains identical to the version reviewed.

Attack Path

**Symlink over ...[truncated 1708 chars]

Remediation
View remediation

Remediation Suggestions

  1. Prefer the bundled references/cities.tsv and resolve its path relative to the installed script instead of using a shared downloaded cache.
  2. If runtime downloading is required, create a private temporary directory and file with mktemp -d and mktemp, under a restrictive umask such as 077.
  3. Register a cleanup trap so temporary data is removed on normal exit and interruption.
  4. Download into a newly created temporary file, validate its format and expected ownership, and move it atomically into a user-private cache directory.
  5. Store persistent cache data under an account-specific cache directory such as ${XDG_CACHE_HOME:-"$HOME/.cache"}/xiaomi-weather, with directory permissions set to 0700.
  6. Reject symbolic links and files not owned by the invoking user. Where supported, use no-follow semantics when opening files.
  7. Pin the remote database to an immutable commit and verify a maintained cryptographic checksum or signature before use.
  8. Do not run the Skill as root or another privileged account.

A safer temporary-download pattern would be:

bash
local tmpdir db
umask 077
tmpdir=$(mktemp -d) || return 1
trap 'rm -rf -- "$tmpdir"' RETURN
db="$tmpdir/cities.tsv"

curl -fsSL --max-time 15 \
  "https://raw.githubusercontent.com/huanghui0906/API/<PINNED_COMMIT>/xiaomi_weather.db" \
  -o "$db" || return 1

# Verify the expected checksum and validate the file format before parsing.
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 (7)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill documents network and shell-dependent behavior but does not declare any explicit tool scope or permissions. This creates a transparency and governance gap: an agent may invoke network access and local command execution without the user or platform having a clear allowlist, increasing the chance of unintended external requests or shell misuse in broader agent environments.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The request URL hard-codes locale=zh_cn, and the script's messages and output are entirely in Chinese. This enforces a specific language/locale without opt-in or an exposed option to choose another locale, which matches the language-policy violation criteria.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill states that unmatched cities are resolved via a remote city database and that weather data comes from Xiaomi services, but it does not clearly warn users that their query terms may be transmitted to third parties. This is primarily a privacy and informed-consent issue: user-provided location searches could reveal sensitive travel, residence, or interest information.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The natural-language description of request parameters explicitly fixes the locale to Chinese, and the document does not mention any user opt-in or language selection. This can violate language/locale policy because it forces a specific locale behavior rather than offering a choice or documenting a necessary region-specific constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The header comments specify the dataset and format only in Chinese, and the city names throughout the file are also Chinese. Because SQP-3 applies to all file types and flags forced language choices without user opt-in or justification, this appears to impose a specific language/locale without explanation.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest describes a weather-query skill using the same data source as the Xiaomi Weather app. However, when a city is not in the built-in table, the script downloads a remote city database from a GitHub raw URL rather than from the Xiaomi source, so part of the behavior depends on a different external dataset. This is a semantic mismatch in the implementation of location resolution, even though the weather data itself still comes from Xiaomi.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script silently fetches a remote city database with curl when a local city match is unavailable. Although the code comment notes that curl networking is needed, there is no user-facing disclosure, prompt, or visible message informing the user that a network request to GitHub will be made.

Content

No source excerpt is available for this finding.