Back to skill

Security audit

geoskill-urban-population-estimation

Security checks across malware telemetry and agentic risk

Overview

The main tool appears to do local population-density processing, but the package also includes under-disclosed network geocoding and broad credential-handling code, including a hardcoded Earthdata password.

Review before installing. The population-estimation entrypoint itself is mostly local, but the package ships extra credential and network helpers that are not clearly disclosed. Do not install it in an environment containing real ~/.netrc, ~/.geoskill/secrets.json, or sensitive environment credentials unless those modules are removed or scoped, the hardcoded Earthdata credentials are removed and rotated, and network/cache behavior is documented or disabled.

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

Lp3

Medium
Category
MCP Least Privilege
Confidence
80% confidence
Finding
The skill declares no permissions, yet its documented or detected capabilities include shell, file read/write, environment access, network, and broader execution features. This creates a trust and review gap: operators may approve or run the skill under the assumption that it is offline and low-risk, while it can access local data, exfiltrate information over the network, or invoke shell operations.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill description presents a local, offline population-estimation workflow, but the analyzed behavior includes geocoding, HTTP downloads, generic downloader logic, credential handling, and even hardcoded fallback Earthdata credentials. This mismatch is dangerous because it conceals materially different behavior from users and reviewers, increasing the risk of unauthorized network access, secret misuse, supply-chain exposure, and collection or transmission of local data beyond the stated purpose.

Context-Inappropriate Capability

High
Confidence
89% confidence
Finding
This credential module is broader than the stated urban population estimation purpose and centralizes access to multiple unrelated secrets, including OpenAI, CMA, FIRMS, EOG, and Earthdata. That expands the skill’s privilege surface and creates unnecessary secret-handling capability inside a skill that should ideally use only the minimum required data-source credentials.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The code reads user-level secret stores and environment credentials from the operator’s home directory, which gives the skill access to sensitive material beyond its explicit manifest purpose. Even though this file does not exfiltrate secrets directly, unauthorized access to local secret sources increases blast radius if other parts of the skill or future changes misuse the returned values.

Description-Behavior Mismatch

Medium
Confidence
99% confidence
Finding
The manifest shows the skill accepts a negative `total_population` value and preserves it through output QA metrics, producing negative density statistics. This is a true input-validation flaw because population counts and densities are semantically non-negative; downstream tools may trust these outputs and make incorrect decisions, trigger failures, or propagate corrupted analytics.

Missing User Warnings

Medium
Confidence
81% confidence
Finding
Geocoding queries are sent to third-party services without any visible user-facing disclosure in this file, which can leak sensitive user-entered locations such as home, workplace, or operational areas. In a geospatial skill, location data is often privacy-sensitive, so silent transmission increases the risk of unintended data exposure even if the network behavior is functionally related to the task.

Missing User Warnings

Medium
Confidence
84% confidence
Finding
Resolved place data is persisted in a cache file under the user's home directory without visible disclosure or consent, which can leave a recoverable history of queried locations on disk. Because geographic queries may reveal sensitive movements or interests, undisclosed local retention can create privacy and forensic exposure on shared or managed systems.

Missing User Warnings

High
Confidence
99% confidence
Finding
The source contains hardcoded fallback credentials, including a plaintext Earthdata username and password. Embedding real or potentially real credentials in code is dangerous because anyone with source access can recover and reuse them, and downstream consumers may unknowingly authenticate with shared credentials.

Natural-Language Policy Violations

Medium
Confidence
84% confidence
Finding
The code hard-codes an Accept-Language header of zh-CN for Nominatim requests, overriding user locale expectations and sending a regional preference to a third-party service without opt-in. This can leak unnecessary contextual information, bias results toward a specific locale, and produce surprising or unfair behavior for users outside that language context.

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

Unpinned Dependencies

Low
Category
Supply Chain
Content
numpy
rasterio
Confidence
93% confidence
Finding
numpy

Unpinned Dependencies

Low
Category
Supply Chain
Content
numpy
rasterio
Confidence
91% confidence
Finding
rasterio

Known Vulnerable Dependency: numpy — 10 advisory(ies): CVE-2014-1859 (Numpy arbitrary file write via symlink attack); CVE-2021-41495 (NumPy NULL Pointer Dereference); CVE-2021-33430 (NumPy Buffer Overflow (Disputed)) +7 more

Critical
Category
Supply Chain
Confidence
84% confidence
Finding
numpy

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