Back to skill

Security audit

geoskill-transfer-learning-rs

Security checks across malware telemetry and agentic risk

Overview

The main classifier appears local, but the package also bundles unrelated credential-reading, geocoding, and download code that is not disclosed in the offline skill description.

Review this package before installing. The classifier entrypoint looks local, but the published artifact contains extra network and credential-handling code that should either be removed or clearly documented and gated behind explicit user opt-in. Treat the hardcoded Earthdata credentials as exposed and avoid using the bundled helper modules unless you intend to grant that access.

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

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill is documented as an offline local-processing tool, yet the analysis indicates capabilities for environment access, file read/write, shell, and network without any declared permissions. Even if some capabilities are only support code, the absence of explicit permission disclosure prevents informed consent and can hide access to local files, secrets, or outbound communications.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This is a strong description-behavior mismatch: the skill claims to be offline transfer-learning/classification, but the detected behavior includes online geocoding/API calls, download logic, credential collection from env/.netrc/secrets files, and even hardcoded Earthdata credentials. That combination materially expands the trust boundary and could expose local secrets or trigger unexpected external network access under a misleading offline description.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The vendored metadata claims the embedded component is for a different skill ('landsat-download') than the declared transfer-learning classifier, which indicates a supply-chain integrity mismatch. Even though this file is only metadata, the mismatch strongly suggests the package may include reused or misplaced code and capabilities that were not reviewed for this skill’s intended purpose, undermining trust in what is actually bundled.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The vendored file list includes download- and credential-related modules despite the skill being described as an offline numpy-equivalent classification workflow. This unjustified capability expansion increases attack surface and creates risk of hidden network access, credential handling, or misuse of sensitive data in a context where such behavior should not exist.

Description-Behavior Mismatch

High
Confidence
96% confidence
Finding
This module introduces network geocoding and local persistence behaviors that do not align with the stated purpose of an offline transfer-learning/classification skill. In this context, unexpected outbound requests and disk writes expand the attack surface, can leak user-supplied place queries to third parties, and create undeclared side effects that users would not reasonably expect from an offline classifier.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
The code sends place queries to external services (Open-Meteo and Nominatim), which is unjustified for an offline classifier and creates an unintended data exfiltration path. Even if the transmitted data seems low sensitivity, location queries can reveal user interests, targets, or operational context, especially when hidden inside a skill advertised as offline.

Context-Inappropriate Capability

Medium
Confidence
87% confidence
Finding
Persisting cache data under the user's home directory creates undeclared local side effects and retains user queries/results beyond process lifetime. In a skill presented as offline classification, this can expose sensitive location inputs to other local users, backup systems, or later compromise, and it is not necessary for the core advertised function.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
This module implements broad credential harvesting and brokerage for multiple external services despite the skill being described as an offline transfer-learning/classification tool. That mismatch materially increases risk because any code importing this module can access user secrets unrelated to the stated purpose, expanding attack surface and creating unjustified secret exposure.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The code reads credentials from environment variables, ~/.geoskill/secrets.json, and ~/.netrc for several third-party services unrelated to the advertised offline workflow. Even without direct exfiltration in this file, centralized access to multiple secret stores is dangerous because it enables downstream code to retrieve and misuse credentials under the guise of a local ML skill.

Intent-Code Divergence

Medium
Confidence
88% confidence
Finding
The docstring says passwords are not cached, but load_user_secrets() copies secrets into the module-global _DEFAULTS and keeps them resident for the process lifetime. This discrepancy can mislead reviewers and users about the true secret-handling behavior, weakening trust and potentially increasing exposure in memory dumps or introspection.

Description-Behavior Mismatch

High
Confidence
89% confidence
Finding
This file introduces full network retrieval capability, including retry, resume, and batch download, even though the skill is ներկայացted as an offline transfer-learning/classification tool. In this context, hidden or unjustified download functionality expands the attack surface, can pull untrusted remote artifacts at runtime, and may bypass user expectations or platform controls around offline-only skills.

Context-Inappropriate Capability

High
Confidence
91% confidence
Finding
The module exposes a generic HTTP download primitive (`safe_download` / `safe_download_many`) that can fetch arbitrary URLs and write attacker-controlled content to disk. For a skill described as offline classification and evaluation, this mismatch is especially concerning because it enables unexpected data ingress, remote model or file substitution, and potential abuse as a covert network-capable component.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The exposed resolve_place() API advertises place resolution and, in both the core path and legacy fallback, can trigger external geocoding requests. In a skill described as offline and numpy-equivalent, this creates an unexpected data egress path that can leak user-supplied place names and environment-derived metadata (for example via headers, timing, or network logs), and it violates the stated trust boundary of an offline skill.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The legacy implementation imports requests and performs live lookups against Open-Meteo and Nominatim, preserving network capability even when the preferred core module fails. This is dangerous because the fallback broadens the attack surface and makes outbound communication resilient to partial failures, enabling silent exfiltration of user inputs in a skill whose stated purpose does not justify any network access.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
User-supplied place queries are transmitted to third-party geocoding services without any visible disclosure or consent mechanism in this file. Hidden transmission of user inputs is a privacy and trust issue, and in this skill context it is more concerning because the package is described as offline and classification-focused, so users are less likely to anticipate external sharing.

Missing User Warnings

High
Confidence
100% confidence
Finding
Hardcoded fallback credentials include a real-looking username and password in source code. This is a direct secret exposure and also creates the possibility that deployments silently authenticate with embedded credentials, causing account compromise, unauthorized service use, and secret propagation via source control or package distribution.

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
94% 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
94% 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
94% 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
90% 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
95% 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
95% 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
96% 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
97% 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
97% confidence
Finding
.netrc

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