Back to skill

Security audit

geoskill-urban-microclimate

Security checks across malware telemetry and agentic risk

Overview

The advertised tool is a local urban microclimate analyzer, but the package also includes under-disclosed network, download, and credential-handling code, including hardcoded Earthdata credentials.

Review this package before installing. The documented microclimate CLI appears local, but the distributed artifact contains extra modules that can contact external geocoding/download services and read user credential files. The hardcoded Earthdata username/password should be removed and rotated by the publisher, and the package should either remove the unused vendored helpers or clearly document and gate them behind explicit user configuration.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
Findings (31)

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill declares no permissions, yet the analyzed implementation appears to exercise environment access, file read/write, shell execution, and network capabilities. This creates a transparency and sandboxing gap: users and orchestrators may approve the skill believing it is offline/local-only when it can access broader resources, increasing the chance of unintended data exposure or command execution.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared purpose is narrowly scoped to urban microclimate analysis, but the implementation reportedly includes unrelated remote-service helpers, caching, generic download logic, centralized credential handling, and even embedded default Earthdata credentials. This mismatch is dangerous because it hides materially broader behavior than users expect, and the credential/default-secret aspect can enable unauthorized remote access, data exfiltration, or abuse of external services.

Description-Behavior Mismatch

Medium
Confidence
89% confidence
Finding
The vendored metadata shows this skill bundles a different capability set ('landsat-download') than its declared purpose of urban microclimate analysis. Scope-mismatched vendored code increases supply-chain and hidden-capability risk because operators may unknowingly ship download functionality, external data access paths, and associated logic that are not expected from the skill description.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The metadata indicates inclusion of modules such as safe_download.py and credentials.py, introducing download and credential-handling capabilities beyond the stated analysis-only scope. Even without proof of active abuse in this file, unnecessary credential and network-related components broaden the attack surface, create opportunities for secret misuse, and make the skill more dangerous because its context does not obviously require those capabilities.

Description-Behavior Mismatch

High
Confidence
92% confidence
Finding
This module introduces broad credential-management capabilities for multiple external services inside a skill whose stated purpose is urban microclimate analytics. While some remote data access may be legitimate, bundling credential harvesting and fallback logic for unrelated services expands the attack surface and enables the skill to access sensitive accounts beyond the expected scope.

Description-Behavior Mismatch

Critical
Confidence
100% confidence
Finding
The code hardcodes a default Earthdata username and password directly in source. Hardcoded credentials can be extracted by anyone with source access, reused in unauthorized contexts, and may expose a real third-party account or encourage insecure secret-distribution practices.

Intent-Code Divergence

Critical
Confidence
99% confidence
Finding
The documentation claims passwords are not hardcoded, but the module in fact embeds fallback credentials. This misleading documentation increases risk because reviewers and users may trust the module and miss live secrets in code, delaying detection and remediation.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
User-supplied place names are sent to third-party geocoding services without any notice or consent mechanism in this module. Place queries can contain sensitive location information, so transmitting them externally creates a privacy and data-handling risk, especially in a geospatial skill where user inputs may reveal home, workplace, or sensitive sites.

Missing User Warnings

Low
Confidence
84% confidence
Finding
Resolved locations are persisted under the user's home directory without disclosure, retention controls, or permission hardening. While not an immediate code-execution flaw, it can expose sensitive location history to other local users, backups, or later processes on shared or managed systems.

Missing User Warnings

High
Confidence
98% confidence
Finding
The fallback credentials are embedded without any clear runtime disclosure or explicit user consent. That creates a silent authentication path using shared secrets, which can surprise users and enable unauthorized service access under another identity.

Natural-Language Policy Violations

Medium
Confidence
75% confidence
Finding
Forcing the Nominatim Accept-Language header to zh-CN for every request can leak an unnecessary locale preference and may bias returned place labels or matching behavior without user awareness. In a geospatial skill, this is primarily a privacy and correctness issue rather than a severe security flaw, but it is still an unjustified request-side preference injection.

Credential Access

High
Category
Privilege Escalation
Content
/ `EARTHDATA_TOKEN` / `FIRMS_MAP_KEY` / `OPENAI_API_KEY` /
  `CMA_API_KEY` / `EOG_USERNAME` / `EOG_PASSWORD` 任何一项显式设置
  都优先于默认值。
- **支持 .netrc**:若 ~/.netrc 中存在 `machine urs.earthdata.nasa.gov`
  行,优先取 .netrc 凭证。
- **支持用户级 secrets 文件** ``~/.geoskill/secrets.json``:Phase 7
  (2026-07-27) 新增。本文件在用户 home,**不** vendor 到任何 skill,
Confidence
78% confidence
Finding
.netrc

Credential Access

High
Category
Privilege Escalation
Content
/ `EARTHDATA_TOKEN` / `FIRMS_MAP_KEY` / `OPENAI_API_KEY` /
  `CMA_API_KEY` / `EOG_USERNAME` / `EOG_PASSWORD` 任何一项显式设置
  都优先于默认值。
- **支持 .netrc**:若 ~/.netrc 中存在 `machine urs.earthdata.nasa.gov`
  行,优先取 .netrc 凭证。
- **支持用户级 secrets 文件** ``~/.geoskill/secrets.json``:Phase 7
  (2026-07-27) 新增。本文件在用户 home,**不** vendor 到任何 skill,
Confidence
78% confidence
Finding
~/.netrc

Credential Access

High
Category
Privilege Escalation
Content
`CMA_API_KEY` / `EOG_USERNAME` / `EOG_PASSWORD` 任何一项显式设置
  都优先于默认值。
- **支持 .netrc**:若 ~/.netrc 中存在 `machine urs.earthdata.nasa.gov`
  行,优先取 .netrc 凭证。
- **支持用户级 secrets 文件** ``~/.geoskill/secrets.json``:Phase 7
  (2026-07-27) 新增。本文件在用户 home,**不** vendor 到任何 skill,
  **不** push 到 GitHub;用于把个人真实凭证(NASA Earthdata bearer
Confidence
78% confidence
Finding
.netrc

Credential Access

High
Category
Privilege Escalation
Content
(2026-07-27) 新增。本文件在用户 home,**不** vendor 到任何 skill,
  **不** push 到 GitHub;用于把个人真实凭证(NASA Earthdata bearer
  token 等)放在 skill 之外。
- **不缓存密码**:每次调用读环境或 .netrc(避免长寿命进程泄露)。
- **统一接口**:`get_earthdata_creds()` / `get_earthdata_token()` /
  `get_firms_key()` / `get_cma_key()` / `get_openai_key()` /
  `get_eog_creds()` 六个 helper。
Confidence
75% confidence
Finding
.netrc

Credential Access

High
Category
Privilege Escalation
Content
"EOG_PASSWORD": "",
}

# .netrc 解析(仅在 UNIX-like / WSL 下 ~/.netrc 可用;Windows 下
# 通常用 %USERPROFILE%\_netrc,但 .netrc 本身仍是约定俗成的名称)。
_NETRC_HOSTS = {
    "urs.earthdata.nasa.gov": ("EARTHDATA_USERNAME", "EARTHDATA_PASSWORD"),
Confidence
80% confidence
Finding
.netrc

Credential Access

High
Category
Privilege Escalation
Content
"EOG_PASSWORD": "",
}

# .netrc 解析(仅在 UNIX-like / WSL 下 ~/.netrc 可用;Windows 下
# 通常用 %USERPROFILE%\_netrc,但 .netrc 本身仍是约定俗成的名称)。
_NETRC_HOSTS = {
    "urs.earthdata.nasa.gov": ("EARTHDATA_USERNAME", "EARTHDATA_PASSWORD"),
Confidence
80% confidence
Finding
~/.netrc

Credential Access

High
Category
Privilege Escalation
Content
}

# .netrc 解析(仅在 UNIX-like / WSL 下 ~/.netrc 可用;Windows 下
# 通常用 %USERPROFILE%\_netrc,但 .netrc 本身仍是约定俗成的名称)。
_NETRC_HOSTS = {
    "urs.earthdata.nasa.gov": ("EARTHDATA_USERNAME", "EARTHDATA_PASSWORD"),
    "firms.modaps.eosdis.nasa.gov": ("FIRMS_MAP_KEY",),
Confidence
76% confidence
Finding
.netrc

Credential Access

High
Category
Privilege Escalation
Content
def _read_netrc(host: str) -> Optional[Tuple[str, ...]]:
    """从 ~/.netrc 读指定 host 的凭证(无 token 格式)。"""
    for path in (Path.home() / ".netrc", Path.home() / "_netrc"):
        if not path.is_file():
            continue
Confidence
88% confidence
Finding
~/.netrc

Credential Access

High
Category
Privilege Escalation
Content
def _read_netrc(host: str) -> Optional[Tuple[str, ...]]:
    """从 ~/.netrc 读指定 host 的凭证(无 token 格式)。"""
    for path in (Path.home() / ".netrc", Path.home() / "_netrc"):
        if not path.is_file():
            continue
        try:
Confidence
88% confidence
Finding
.netrc

Credential Access

High
Category
Privilege Escalation
Content
def _resolve(name: str) -> str:
    """env > 用户 secrets > .netrc > 默认. 空字符串视为未设."""
    env_val = os.environ.get(name, "").strip()
    if env_val:
        return env_val
Confidence
74% confidence
Finding
.netrc

Credential Access

High
Category
Privilege Escalation
Content
def _resolve_with_netrc(env_name: str, netrc_host: str, field_index: int) -> str:
    """env > 用户 secrets > .netrc > 默认."""
    env_val = os.environ.get(env_name, "").strip()
    if env_val:
        return env_val
Confidence
76% confidence
Finding
.netrc

Credential Access

High
Category
Privilege Escalation
Content
解析顺序:
    1. env: EARTHDATA_USERNAME / EARTHDATA_PASSWORD
    2. ~/.geoskill/secrets.json
    3. .netrc: machine urs.earthdata.nasa.gov
    4. _DEFAULTS 兜底
    """
    u = _resolve_with_netrc("EARTHDATA_USERNAME", "urs.earthdata.nasa.gov", 0)
Confidence
83% confidence
Finding
.netrc

Credential Access

High
Category
Privilege Escalation
Content
都优先于默认值。
- **支持 .netrc**:若 ~/.netrc 中存在 `machine urs.earthdata.nasa.gov`
  行,优先取 .netrc 凭证。
- **支持用户级 secrets 文件** ``~/.geoskill/secrets.json``:Phase 7
  (2026-07-27) 新增。本文件在用户 home,**不** vendor 到任何 skill,
  **不** push 到 GitHub;用于把个人真实凭证(NASA Earthdata bearer
  token 等)放在 skill 之外。
Confidence
77% confidence
Finding
secrets.json

Credential Access

High
Category
Privilege Escalation
Content
_DEFAULTS: dict[str, str] = {
    "EARTHDATA_USERNAME": "ruiduobao",
    "EARTHDATA_PASSWORD": "Ruiduobao123",
    "EARTHDATA_TOKEN": "",  # 用户级 secrets.json 提供(不走默认值以免推到 GitHub)
    "FIRMS_MAP_KEY": "",
    "CMA_API_KEY": "",
    "OPENAI_API_KEY": "",
Confidence
96% confidence
Finding
secrets.json

VirusTotal

VirusTotal findings are pending for this skill version.

View on VirusTotal

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
tests/conftest.py:15