Back to skill

Security audit

geoskill-web-map-generation

Security checks across malware telemetry and agentic risk

Overview

This map skill does render local maps, but it also ships unrelated code that can read local credentials and contact external services without clear disclosure.

Review this skill before installing. Use it only in a constrained environment or after removing the unused credential, download, and geocoding modules; avoid running it where ~/.netrc, ~/.geoskill/secrets.json, or relevant API keys are present unless you trust the publisher and need those integrations.

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

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill metadata declares no permissions, yet the detected capabilities include environment access, file read/write, shell use, network access, and other code behaviors beyond what a simple offline map renderer should need. This creates a trust and sandboxing gap: users or orchestrators may approve the skill under a much weaker security posture than its actual behavior requires, increasing the chance of unintended secret access, file modification, or outbound communication.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
This is a serious description-to-behavior mismatch: the skill presents itself as a local web-map generator, but analysis indicates unrelated network operations, geocoding, credential handling, secret-file reads, and even hardcoded fallback credentials. In this context, the mismatch is dangerous because users would reasonably supply local geospatial data expecting offline processing, while the code may access secrets, contact remote services, and perform actions far outside the declared scope.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The vendored metadata shows this skill includes a separate 'landsat-download' component with files for downloading, AOI handling, checks, and credentials, which does not align with the declared purpose of simple web map generation. This kind of capability mismatch is a supply-chain and least-privilege risk because it introduces unexpected functionality that could enable data access, network activity, or credential use beyond what users would reasonably expect from the skill description.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
Including bundled download and credential-handling code in a skill advertised only for web map generation expands the attack surface and creates hidden capability for external access or secret processing. In this context, the mismatch makes the skill more dangerous because users and reviewers may grant trust appropriate for a rendering tool while the package contains code that can fetch remote data or interact with credentials.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
This module is a centralized credential broker that reads and returns credentials for multiple external services, including hardcoded fallback credentials for Earthdata. In the context of a web-map-generation skill, bundling broad credential access increases blast radius and creates a reusable primitive for secret harvesting or unintended external-service access far beyond the stated functionality.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The code explicitly reads secrets from environment variables, ~/.netrc, and ~/.geoskill/secrets.json for several third-party services without strong evidence that all are necessary for the advertised map-generation purpose. In a skill ecosystem, this kind of broad credential discovery is dangerous because it normalizes access to user-local secrets and can expose or misuse credentials if other code paths call these helpers.

Intent-Code Divergence

Medium
Confidence
88% confidence
Finding
The documentation claims passwords are not cached, but load_user_secrets() copies secrets into the process-global _DEFAULTS dictionary and retains them after first load. This mismatch is security-relevant because operators may rely on the stated behavior when assessing memory exposure, secret rotation, and long-lived process risk.

Missing User Warnings

Medium
Confidence
76% confidence
Finding
User-supplied place queries are transmitted to third-party geocoding services without any disclosure or consent mechanism in this module, which creates a real privacy and data-handling risk. Even if the input is 'just a place name,' it can still reveal sensitive locations, project interests, or operational context, especially in a geospatial workflow where AOIs may correspond to confidential sites.

Missing User Warnings

High
Confidence
100% confidence
Finding
The module contains hardcoded fallback credentials: an Earthdata username and password embedded in source. Hardcoded credentials are inherently dangerous because anyone with source access can reuse them, and downstream code may silently authenticate with shared secrets without user awareness.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The module sends user-provided place queries to third-party geocoding services, which can disclose sensitive locations, project names, or investigation targets without explicit consent or local-only fallback. In the context of a mapping skill, users may reasonably provide operationally sensitive place names, so silent transmission to external services creates a real privacy and data-handling risk.

Natural-Language Policy Violations

Medium
Confidence
80% confidence
Finding
Forcing `Accept-Language: zh-CN,zh;q=0.9` without user choice can influence provider responses and may leak assumptions about the user's locale or intended geography. While not severe on its own, it creates avoidable privacy and correctness issues, especially for a general-purpose map skill that may be used in other regions or languages.

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
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
84% 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_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
89% 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
87% 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
88% 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
89% 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