Back to skill

Security audit

geoskill-time-series-classification

Security checks across malware telemetry and agentic risk

Overview

The main classifier appears local, but the package also ships undeclared credential and network helper code that does not fit the stated offline crop-classification purpose.

Review this package before installing. The classifier may run locally, but the bundled helper code can access local credential stores and external geocoding services if used. Install only if you trust the publisher, and avoid running it in an environment with sensitive ~/.netrc or ~/.geoskill/secrets.json credentials unless those helpers are removed or clearly gated.

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 (29)

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill documentation declares no permissions, yet the analyzed behavior indicates access to environment variables, local files, network, shell execution, and file writes. This creates a transparency and trust problem: users may run the skill assuming offline/local NDVI processing while the implementation can access sensitive data and external services.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This is a strong description-behavior mismatch: a crop-classification skill allegedly limited to NDVI time-series processing also performs geocoding, external API access, local caching, credential discovery from env/.netrc/secrets.json, and even contains hardcoded default credentials. That combination materially increases risk of secret exposure, unintended data exfiltration, and abuse of third-party accounts, especially because the SKILL.md explicitly frames the tool as offline/local processing.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The vendored core metadata declares the skill as 'landsat-download', which does not match the stated NDVI time-series classification purpose of this package. This kind of provenance mismatch is a supply-chain integrity issue because it can indicate copied or substituted core components, mispackaging, or tampering that causes reviewers and automated tooling to trust the wrong codebase.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
This credential module is materially broader than the skill’s stated NDVI time-series feature extraction and RandomForest crop classification purpose. It centralizes access to multiple external-service credentials, expanding the blast radius: any code path in the skill can silently obtain unrelated secrets, which is dangerous in an agent/skill setting where least-privilege and tight scope are expected.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
Managing OPENAI_API_KEY is not justified by the described geospatial classification workflow and creates unnecessary secret-access capability. In an agent skill, unrelated API-key access increases the chance of unauthorized use, hidden network egress, or lateral abuse of a user’s broader account permissions.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
User-supplied place names are sent to Open-Meteo and optionally Nominatim without any visible consent, warning, or offline-first enforcement at the API boundary. In a geospatial workflow, place queries can reveal sensitive operational interests, user location intent, or project targets, so silent transmission to third-party services is a real privacy/security concern.

Natural-Language Policy Violations

Medium
Confidence
86% confidence
Finding
The code hard-codes an Accept-Language header of zh-CN/zh for Nominatim requests, overriding user locale expectations without consent. While not a severe exploit primitive, it can leak assumptions about user region or deployment context and may influence provider responses in ways the user did not request.

Missing User Warnings

High
Confidence
99% confidence
Finding
The module contains hardcoded fallback Earthdata credentials, including a plaintext password, and automatically loads user secrets from the home directory without explicit runtime consent. Hardcoded credentials are a direct secret exposure, and implicit secret loading increases the risk that unrelated or malicious code inside the skill can access sensitive accounts without the user realizing it.

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
88% 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
88% 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
88% 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
86% 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
89% 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
89% 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
90% 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
95% 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
95% 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
95% 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
84% 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
91% 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
99% confidence
Finding
secrets.json

Credential Access

High
Category
Privilege Escalation
Content
# 用户级 secrets 文件位置(在用户 home,**不** vendor 到 skill 内部)。
# Phase 7 (2026-07-27): 包含 NASA Earthdata bearer token 等真实凭证。
USER_SECRETS_PATH = Path.home() / ".geoskill" / "secrets.json"

# 是否已加载过用户级 secrets(避免每次调用都重读)
_user_secrets_loaded = False
Confidence
92% confidence
Finding
secrets.json

Credential Access

High
Category
Privilege Escalation
Content
def load_user_secrets(path: Optional[Path] = None, *, force: bool = False) -> bool:
    """从 ``~/.geoskill/secrets.json`` 加载用户级凭证到 _DEFAULTS.

    Phase 7 (2026-07-27): 第一次调用自动加载(lazy)。之后每个 helper
    调用也会 lazy 加载,除非显式 ``force=True`` 强制重读。返回 True
Confidence
94% confidence
Finding
secrets.json

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 兜底
    """
Confidence
84% confidence
Finding
secrets.json

Credential Access

High
Category
Privilege Escalation
Content
解析顺序:
    1. env: EARTHDATA_TOKEN
    2. ~/.geoskill/secrets.json
    3. .netrc: machine urs.earthdata.nasa.gov account <TOKEN>
    4. _DEFAULTS(通常为空)
    """
Confidence
83% 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