Back to skill

Security audit

geoskill-lulc-classification-ml

Security checks across malware telemetry and agentic risk

Overview

The advertised classifier is mostly local, but the package also contains undeclared credential and network helpers, including hardcoded Earthdata credentials, so it should be reviewed before installation.

Install only after reviewing or removing the unused credential, geocoding, and download helper modules. Avoid using it on machines with sensitive ~/.netrc or ~/.geoskill/secrets.json files unless you accept that bundled code can read them, rotate the exposed Earthdata credential, and do not rely on reported real-image accuracy without independent ground-truth labels.

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

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This is a serious description-behavior mismatch: the skill is presented as an offline local land-cover classifier, but the analyzed behavior reportedly includes online geocoding, HTTP downloading, credential management, and even hardcoded NASA Earthdata fallback credentials. Hidden network access and embedded credentials can exfiltrate user data, access third-party accounts without informed consent, and violate the user's trust boundary because operators may run the skill expecting fully local processing.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
This file implements broad credential-harvesting and secret-resolution functionality that is not tightly scoped to the stated land-cover-classification purpose. In this skill context, adding generic access to environment variables, ~/.netrc, and ~/.geoskill/secrets.json meaningfully expands the attack surface and enables unrelated secret access if any downstream code invokes these helpers.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
Support for OPENAI_API_KEY is unrelated to pixel-wise land-cover classification and gives the skill a path to access a high-value API secret with no clear functional justification. In an adversarial or compromised skill, this kind of latent secret-access capability can be used for credential theft or unauthorized API usage.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The module supports additional unrelated service credentials (FIRMS, CMA, EOG), which broadens access to user secrets beyond what the land-cover-classification use case appears to need. Even if not exfiltrated here, centralizing access to multiple third-party secrets increases the blast radius of any later misuse or compromise.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The documentation claims passwords are not cached, but load_user_secrets() copies secrets.json values into the process-global _DEFAULTS dictionary and retains them for the process lifetime. This mismatch can mislead reviewers and users about secret residency and increases the chance of accidental exposure through debugging, memory inspection, or later code paths.

Description-Behavior Mismatch

High
Confidence
93% confidence
Finding
This land-cover classification skill includes broad place-resolution and network geocoding functionality that is not tightly scoped to the stated ML classification purpose. In an agent setting, this expands the attack surface by allowing user-supplied place strings to trigger outbound requests and external data flows, creating unnecessary privacy, dependency, and misuse risks even if the code is not overtly malicious.

Context-Inappropriate Capability

High
Confidence
96% confidence
Finding
The code sends user-provided place queries to external services (Open-Meteo and Nominatim), which can leak sensitive user intent, project locations, or operational context to third parties. Because this behavior is embedded in a skill whose stated purpose is land-cover classification rather than geocoding, the network exfiltration path is unexpected and increases risk in environments that assume offline or bounded processing.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
In real-input mode, the skill generates pseudo-labels from the same image and then reports validation accuracy against those derived labels, which can materially misrepresent model quality as supervised classification. This creates a data-integrity risk: operators may trust inflated or meaningless accuracy metrics and make downstream land-use decisions based on unsupported results.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The function sends user-supplied place names to third-party geocoding services without any built-in disclosure, consent gate, or obvious privacy control. In a geospatial workflow, place queries may reveal sensitive project locations, customer sites, or analyst interests, so silent transmission to external services creates a meaningful privacy and data-governance risk.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The code persists resolved place data to disk in the user’s home directory without warning, retention limits, or explicit consent. Even if the data is not highly sensitive by design, AOI queries and derived manifests can reveal locations of interest and remain recoverable long after execution, creating avoidable privacy exposure on shared or managed systems.

Missing User Warnings

High
Confidence
100% confidence
Finding
The code contains hardcoded fallback credentials, including a plaintext Earthdata username and password, directly in source. Hardcoded secrets are immediately reusable by anyone with repository access, are difficult to rotate safely, and in this case expose real authentication material unrelated to the user's runtime configuration.

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
85% 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
85% 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
85% 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
83% 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
84% 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
84% 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
82% 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
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
        try:
Confidence
90% 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
81% 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
86% 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
86% confidence
Finding
.netrc

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(通常为空)
    """
    return _resolve("EARTHDATA_TOKEN")
Confidence
79% 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
88% 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