Back to skill

Security audit

geoskill-profile-chart-generator

Security checks across malware telemetry and agentic risk

Overview

The main chart generator is local, but the package bundles under-disclosed credential, network lookup, download, and hardcoded-password code that needs Review before installation.

Review this before installing in an environment with real credentials or sensitive geospatial data. The documented chart command appears local, but the package should remove or isolate the credential module, delete and rotate the embedded Earthdata password, disclose or remove geocoding/network helpers, and fix the vendored provenance metadata.

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

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
A strong description-behavior mismatch is a real security concern because it can conceal unexpected capabilities such as credential handling, remote downloads, geocoding, and unrelated data-processing logic under an innocuous chart-generation label. Users may grant trust or execute the skill expecting offline local raster processing, while hidden networked and credential-related behavior expands the attack surface and can expose secrets or fetch untrusted content.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The vendored metadata claims this skill includes a different component, 'landsat-download', which does not align with the declared purpose of generating profile charts from sampled elevation or imagery values. This kind of dependency or provenance mismatch is a supply-chain integrity issue because it can indicate the wrong code was bundled, a substituted component, or tampered metadata, making review and trust decisions unreliable.

Context-Inappropriate Capability

High
Confidence
94% confidence
Finding
This credential manager exposes accessors for multiple unrelated services, including OpenAI, CMA, FIRMS, and EOG, despite the skill being described as a profile chart generator. Broad secret-handling capability increases the chance the skill can access credentials beyond what is necessary, violating least privilege and creating unnecessary exposure if the module is reused or abused.

Context-Inappropriate Capability

High
Confidence
90% confidence
Finding
The code loads a user-level secrets file and merges any recognized secret values into runtime defaults, enabling the skill to access sensitive credentials from outside its own scope. In the context of a chart-generation skill, this broad secret ingestion is more dangerous because it lets a low-risk feature silently inherit high-value credentials unrelated to its stated purpose.

Intent-Code Divergence

Critical
Confidence
99% confidence
Finding
The module documentation states that passwords are not hardcoded, but the code embeds fallback credentials directly in `_DEFAULTS`, including a username and password. Hardcoded credentials are immediately dangerous because anyone with source access can recover them, and the misleading documentation may reduce scrutiny and delay rotation.

Description-Behavior Mismatch

High
Confidence
92% confidence
Finding
The code performs live external geocoding requests to Open-Meteo and Nominatim using user-supplied place names, which expands the skill’s data flows beyond simple local chart generation. This creates privacy and unexpected network-exfiltration risk because user inputs are sent to third-party services, and the fallback logic preserves this capability even when the unified core is unavailable.

Context-Inappropriate Capability

Medium
Confidence
87% confidence
Finding
The exported resolve_place API provides standalone place-resolution behavior that is broader than the stated profile-chart/CSV purpose, increasing attack surface and enabling unadvertised third-party data sharing. While not inherently malicious, hidden capability creep is a security concern because downstream consumers may invoke networked geocoding without realizing it.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The skill’s stated purpose is to generate a profile chart and CSV, but it also writes a GeoTIFF containing the full DEM raster to the output directory. If the input DEM is sensitive, licensed, or larger in scope than needed for the requested profile, this creates unnecessary data disclosure and retention beyond user expectations.

Intent-Code Divergence

Low
Confidence
81% confidence
Finding
Although the privacy note says processing is offline and no user data is uploaded, the code persists the full command line into an output manifest, which may include sensitive file paths, coordinates, titles, or other user-supplied arguments. This is a local privacy and metadata leakage issue because it stores more user context than is necessary for the task.

Missing User Warnings

Medium
Confidence
83% confidence
Finding
User-provided place queries are sent to third-party geocoding services without any disclosure or consent mechanism in this component. Even if queries seem low sensitivity, location strings can reveal personal, operational, or proprietary information, and the skill context makes this relevant because chart generation does not obviously imply third-party transmission of place names.

Missing User Warnings

High
Confidence
99% confidence
Finding
The `_DEFAULTS` dictionary contains hardcoded fallback credentials, which means the application may authenticate successfully even when operators have not explicitly configured secrets. This is dangerous because it hides insecure behavior, promotes credential reuse, and can expose a real account to anyone who obtains the code.

Natural-Language Policy Violations

Medium
Confidence
76% confidence
Finding
Forcing the Accept-Language header to Chinese without user choice can influence third-party responses and silently leak locale assumptions about the environment or expected user population. This is primarily a privacy, transparency, and correctness issue rather than a direct exploit primitive, but it can cause misleading or biased results for non-Chinese users.

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
86% 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
86% 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
86% 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
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
87% 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
87% 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
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
Confidence
91% 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
91% 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
84% 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
88% 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
80% 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