Back to skill

Security audit

geoskill-snowmelt-runoff-modeling

Security checks across malware telemetry and agentic risk

Overview

The advertised snowmelt model is mostly a local offline CLI, but the package also bundles under-disclosed credential and network helper code that does not fit the stated purpose.

Review this package before installing in an environment with real credentials or sensitive project locations. The normal snowmelt command appears local, but the bundled helper modules should be treated as broader geospatial infrastructure code; remove or disable the credential/geocoding helpers unless you explicitly need them, and do not rely on the hardcoded Earthdata fallback credentials.

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 Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (33)

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The vendored core metadata claims the bundled code is for a different skill ('landsat-download') than this package's stated snowmelt-runoff purpose, indicating a supply-chain integrity or packaging mismatch. Even if accidental, this can cause the wrong vendored components to be trusted, audited, or loaded, undermining provenance checks and increasing the risk of hidden functionality or missed vulnerabilities.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The AOI helper performs outbound requests to Open-Meteo and Nominatim and also supports persistent local caching, which goes beyond the stated snowmelt-runoff modeling function and can expose user-supplied place names to third parties. In this skill context, geographic queries may reveal sensitive project locations, so undisclosed network and storage side effects create a real privacy and supply-chain boundary issue even if the code is not overtly malicious.

Intent-Code Divergence

Medium
Confidence
87% confidence
Finding
The docstring claims ambiguous place handling will return candidates rather than silently selecting the first, but resolve_place still sorts candidates and auto-selects one result. This can cause incorrect AOI selection without user confirmation, leading downstream hydrologic modeling to run on the wrong region and potentially produce misleading outputs.

Description-Behavior Mismatch

High
Confidence
90% confidence
Finding
This credential manager is materially broader than the declared snowmelt-runoff modeling scope, exposing access paths for multiple external services unrelated to the stated task. In a skill context, unnecessary credential-handling surface increases the chance of secret misuse, lateral capability expansion, and supply-chain abuse even if no exfiltration code is shown here.

Context-Inappropriate Capability

Medium
Confidence
83% confidence
Finding
Supporting OpenAI API credential retrieval is out of scope for a snowmelt hydrology skill and creates an unnecessary path to access sensitive user secrets. Even without direct transmission in this file, retrieving unrelated API keys expands the blast radius if the skill or a downstream component is compromised.

Context-Inappropriate Capability

Medium
Confidence
84% confidence
Finding
FIRMS, CMA, and EOG credential support is unrelated to the declared degree-day snowmelt model and broadens the module's ability to access external services. In a narrowly scoped modeling skill, this overreach is risky because it normalizes secret access beyond user expectations and complicates review of what the skill can do.

Intent-Code Divergence

High
Confidence
99% confidence
Finding
The docstring explicitly claims passwords are not hardcoded, yet the module contains hardcoded fallback credentials including a plaintext username and password. Hardcoded secrets in source control are a direct secret-exposure vulnerability and the misleading documentation increases the likelihood they remain unnoticed and deployed.

Intent-Code Divergence

Medium
Confidence
88% confidence
Finding
The module claims not to cache passwords, but it loads user secrets once and stores them in the mutable _DEFAULTS structure for later reuse. Retaining secrets in process memory longer than documented increases exposure to accidental reuse, debugging leaks, and compromise of long-lived processes.

Description-Behavior Mismatch

High
Confidence
90% confidence
Finding
This file adds broad place-resolution and external geocoding behavior that is not aligned with the declared snowmelt-runoff modeling purpose. Scope creep like this increases attack surface, enables unsolicited network egress, and can leak user-supplied locations to third-party services without a clear need tied to the skill’s stated function.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The module performs outbound HTTP requests to Open-Meteo and Nominatim, creating an unnecessary external data-flow for a snowmelt-modeling skill as described. This can expose sensitive place queries, introduce dependency on untrusted remote responses, and expand the skill’s capability beyond least privilege.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
Place queries are transmitted to external geocoding providers without any visible disclosure or consent mechanism in the code path. Because AOI inputs can encode sensitive locations, this creates a privacy leak to third-party services that is especially relevant in a geospatial modeling skill where user locations may be proprietary or operationally sensitive.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
Resolved place queries are stored persistently under the user's home directory by default, without warning or explicit consent. That creates a local privacy exposure because place names and derived AOI data may remain on disk and be accessible to other local users, backups, or later processes beyond the original task.

Missing User Warnings

High
Confidence
99% confidence
Finding
Plaintext fallback credentials are embedded in code and silently used if user configuration is absent. Silent use of hardcoded credentials is dangerous because it can cause unauthorized shared-account use, secret disclosure through source distribution, and unnoticed dependency on compromised credentials.

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
74% 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
74% 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
74% 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
72% 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
74% 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
74% 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
78% 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
86% 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
86% 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
80% 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
75% 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

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