Back to skill

Security audit

Cs Qweather Alert

Security checks for vulnerabilities and agentic risk

Overview

This weather skill is mostly coherent, but it handles API credentials in ways that could leak them if configuration is changed or unsafe hosts are used.

Review this before installing if your QWeather JWT has meaningful account privileges. Use only a trusted HTTPS QWeather API host, avoid relying on a shared ~/.openclaw/.env file, prefer passing credentials explicitly, and periodically delete /tmp/cslog and scripts/data/location.json if location-query history is sensitive.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/qweather_utils.py:100
Finding

JWT bearer token can be transmitted to an arbitrary or plaintext HTTP host

Content
View full analysis
str: val = arg_val or os.environ.get(env_var) if not val: print(f"Error: missing {description}", file=sys.stderr) print(f"Set environment variable {env_var} or pass it as an argument", file=sys.stderr) sys.exit(1) val = val.strip().rstrip("/") if not val.startswith(("http://", "https://")): val = "https://" + val return val ``` The resulting host is used to construct authenticated requests: ```python url = f"{host}/geo/v2/city/lookup?location={urllib.parse.quote(city_name)}&number=1" headers = { "Authorization": f"Bearer {token}", "Accept": "application/json", } result = api_get(url, headers, log_prefix="qweather-geo") ``` The same pattern appears in each weather endpoint: ```python url = f"{host}/v7/weather/now?location={location_id}" headers = { "Authorization": f"Bearer {token}", "Accept": "application/json", } return api_get(url, headers, log_prefix="qweather-get-weather-now") ``` ```python req_headers = dict(headers) req_headers["Accept-Encoding"] = "gzip" req = urllib.request.Request(url, headers=req_headers) try: with urllib.request.urlopen(req, timeout=15) as resp: ``` ### Technical Analysis The API host can come from either the `--host` command-line argument or the `QWEATHER_API_HOST` environment variable. Validation only checks whether the value begins with `http://` or `https://`; it does not: - Require TLS. - Restrict the destination to an authorized QWeather domain. - Reject IP literals, unexpected p ...[truncated 2011 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/qweather_utils.py:17
Finding

Automatic loading of a shared credential-bearing environment file exceeds least privilege

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/qweather_utils.py:132
Finding

Predictable shared temporary logs lack secure creation and expose request metadata

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (15)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill is presented as a simple weather-query utility, but it also reads local secrets from ~/.myjwtkey/last-token.dat, loads environment data from ~/.openclaw/.env, sends authenticated requests to a configurable external host, and persists logs/cache locally. Those side effects materially expand the trust boundary; if users or the runtime assume this is 'just weather lookup,' they may unintentionally grant access to secrets and local storage without informed consent.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill is presented as a simple weather-query utility, but it also reads local secrets from ~/.myjwtkey/last-token.dat, loads environment data from ~/.openclaw/.env, sends authenticated requests to a configurable external host, and persists logs/cache locally. Those side effects materially expand the trust boundary; if users or the runtime assume this is 'just weather lookup,' they may unintentionally grant access to secrets and local storage without informed consent.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

The skill is presented as a simple weather-query utility, but it also reads local secrets from ~/.myjwtkey/last-token.dat, loads environment data from ~/.openclaw/.env, sends authenticated requests to a configurable external host, and persists logs/cache locally. Those side effects materially expand the trust boundary; if users or the runtime assume this is 'just weather lookup,' they may unintentionally grant access to secrets and local storage without informed consent.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The dotenv load call at this line explicitly reads a .env file from the user's home directory, which is a credential-access behavior. Even if intended for convenience, it grants the skill access to potentially sensitive secrets unrelated to weather queries, increasing the blast radius if the code is reused, modified, or combined with other components.

Content

Scanner excerpt · scripts/qweather_utils.py (reported line 17)May include surrounding context.

python
import urllib.parse
import datetime as dt

# 尝试加载 dotenv(标准方式读取 .env 文件)
try:
    import dotenv
    dotenv.load_dotenv(os.path.expanduser("~/.openclaw/.env"), override=True)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/qweather_utils.py (reported line 20)May include surrounding context.

python
# 尝试加载 dotenv(标准方式读取 .env 文件)
try:
    import dotenv
    dotenv.load_dotenv(os.path.expanduser("~/.openclaw/.env"), override=True)
except ImportError:
    pass

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill advertises network, file, environment, and shell-capable behavior but does not declare any explicit tool scope or permission boundaries. In an agent environment, this weakens least-privilege controls and makes it harder for reviewers or the runtime to constrain access to sensitive resources like local token files, env vars, logs, and arbitrary outbound hosts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill states that queried city-location data is cached permanently on disk, but it does not meaningfully warn users about the privacy and retention implications. Even if city names are not highly sensitive in every case, repeated queries can reveal user interests, travel patterns, or monitored locations, and indefinite retention increases exposure if the host is shared or later compromised.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring, CLI help text, and examples are written entirely in Chinese, which imposes a specific language on users without offering an alternative locale or opt-in. The policy explicitly flags language or locale constraints when the skill does not provide user choice or a documented justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code file contains natural-language docstrings, comments, and user-facing error/output strings in Chinese, effectively forcing a specific language for operators and users. The policy allows locale constraints only when explicitly justified or when users are offered a language choice, which is not present here.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Automatically loading environment variables from ~/.openclaw/.env gives the module broad access to secrets from a fixed user-local file, regardless of whether weather lookup needs them. In an agent skill, this is dangerous because it silently widens the trust boundary and may expose unrelated credentials to code paths, logs, or downstream requests.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The utility reads a JWT token from a fixed personal file in the user's home directory when no argument is supplied. That expands the skill's access to unrelated local secrets and creates implicit credential use outside the stated weather-query purpose, which is risky in an agent/plugin context where users may not expect filesystem secret discovery.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

This JSON dataset uses only Chinese place names and Chinese-language administrative values throughout, which can amount to an implicit language restriction. Because the file provides no natural-language indication that the skill is intentionally China-specific or that language choice is user-selectable, it may violate the policy against forcing a specific language without opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

This file contains natural-language documentation, CLI help text, and status/error messages exclusively in Chinese. Under the policy, forcing a specific language without user choice is a natural-language policy violation unless the locale restriction is explicitly documented and justified, which is not present here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The parser description, argument help strings, and printed status/error messages are all presented only in Chinese. This constrains the skill to a single language without offering the user a choice, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

This is a natural-language policy issue because the skill forces a specific language/locale in its docstring and examples, and the same pattern continues in CLI help and status output. The file does not indicate that the tool is intentionally region-specific or provide any user opt-in for language selection.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.