Back to skill

Security audit

geoskill-agriculture-subsidy-verification

Security checks across malware telemetry and agentic risk

Overview

The core verifier is a plausible local geospatial tool, but the package also includes undisclosed credential, network, cache, and download helpers that do not fit the stated offline-only privacy promise.

Review this package before installing in any sensitive environment. The local verifier may be useful, but the bundled credential manager, hardcoded Earthdata credentials, home-directory secret reads, geocoding cache, and outbound geocoding/download helpers should be removed, disabled, or clearly documented with explicit user control.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (25)

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill documentation declares an offline/local geospatial verification workflow, yet the static analysis indicates capabilities for environment access, file read/write, network, and shell without any explicit permission declaration. This creates a transparency and trust problem: an operator may run the skill believing it is constrained, while it may access local data, invoke commands, or communicate externally if the implementation supports those capabilities.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
This is a significant description-behavior mismatch: the skill claims to perform local subsidy verification, but the detected behavior includes unrelated geocoding, external network access, generic downloading, centralized credential handling, and even embedded default credentials. In this context, those hidden or extraneous capabilities are dangerous because they can enable data exfiltration, unauthorized service usage, supply-chain expansion, and misuse of credentials far beyond the stated agricultural compliance task.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
This credential module manages multiple external-service credentials that are not justified by the stated agriculture subsidy verification purpose, materially expanding the skill's privilege surface. In a skill context, broad credential brokerage is dangerous because any downstream code can reuse these helpers to access unrelated services, increasing the chance of credential misuse, data exfiltration, or hidden secondary capabilities.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
FIRMS, CMA, and EOG credential support appears unrelated to the narrow subsidy-verification workflow described for this skill. Unnecessary credential access broadens attack surface and makes the skill capable of interacting with unrelated data providers without clear user expectation or least-privilege justification.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
FIRMS, CMA, and EOG credential support appears unrelated to the narrow subsidy-verification workflow described for this skill. Unnecessary credential access broadens attack surface and makes the skill capable of interacting with unrelated data providers without clear user expectation or least-privilege justification.

Context-Inappropriate Capability

Medium
Confidence
85% confidence
Finding
The file sends user-supplied place names to third-party geocoding services (Open-Meteo and Nominatim), which is outside the narrow subsidy-verification purpose stated in the manifest and creates a data-sharing boundary with external providers. In a compliance-oriented agriculture workflow, submitted parcel/place information may be sensitive operational data, so undisclosed external transmission increases privacy and supply-chain risk.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The resolver sends user-supplied place names to third-party geocoding services without any disclosure or explicit consent in this module. In a subsidy-verification context, place queries may reveal sensitive farm, parcel, or investigation targets to external providers, creating unnecessary data-sharing and privacy risk.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
Resolved place queries are persisted under the user's home directory, which can leave a durable record of sensitive locations and operational activity. In this agricultural subsidy-compliance setting, cached names may expose farmer identities, parcel targets, or enforcement investigations to other local users, backup systems, or forensic review.

Missing User Warnings

High
Confidence
100% confidence
Finding
The module contains hardcoded fallback credentials, including a non-empty Earthdata username and password, despite comments claiming secrets should not be hardcoded. Hardcoded credentials are highly dangerous because they can be extracted from source control, reused across deployments, and silently authenticate external access without operator awareness.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The HTTP requests include raw user-provided place queries in outbound requests without any warning or consent mechanism in this file. Even if the query is only a place name, in this skill context it can reveal sensitive farm, parcel, or subsidy-investigation targets to external services and logs maintained by those providers.

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(name: str) -> str:
    """env > 用户 secrets > .netrc > 默认. 空字符串视为未设."""
    env_val = os.environ.get(name, "").strip()
    if env_val:
        return env_val
Confidence
82% 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
90% 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
83% confidence
Finding
.netrc

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
83% 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
91% confidence
Finding
secrets.json

Unpinned Dependencies

Low
Category
Supply Chain
Content
numpy
rasterio
geopandas
shapely
Confidence
95% confidence
Finding
numpy

Unpinned Dependencies

Low
Category
Supply Chain
Content
numpy
rasterio
geopandas
shapely
Confidence
95% confidence
Finding
rasterio

Unpinned Dependencies

Low
Category
Supply Chain
Content
numpy
rasterio
geopandas
shapely
Confidence
95% confidence
Finding
geopandas

Unpinned Dependencies

Low
Category
Supply Chain
Content
numpy
rasterio
geopandas
shapely
Confidence
95% confidence
Finding
shapely

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