Back to skill

Security audit

Nexapi

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a coherent API-client helper, with expected network calls and local configuration, but users should be careful with API-key storage and endpoint overrides.

Install only if you trust the API service and need this integration. Keep the API key scoped and rotated, avoid setting the base URL or health path to untrusted hosts, and store the config file in a private location with owner-only permissions.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (5)

Tainted flow: 'CONFIG_PATH' from os.getenv (line 17, credential/environment) → pathlib.Path.write_text (file write)

Medium
Category
Data Flow
Content
def save_config(config):
    CONFIG_PATH.write_text(json.dumps(config, ensure_ascii=False, indent=2), encoding="utf-8")


def auth_set(api_key=None):
Confidence
91% confidence
Finding
CONFIG_PATH is derived from an environment variable and then written without validation, so an attacker controlling the process environment could redirect writes to arbitrary filesystem locations accessible to the running user. In this script, that risk is more significant because the file may contain an API key, turning the write into both arbitrary file modification and credential exposure.

Tainted flow: 'CACHE_PATH' from os.getenv (line 16, credential/environment) → pathlib.Path.write_text (file write)

Medium
Category
Data Flow
Content
apis = discover_apis_from_health()
    if not apis:
        return {}
    CACHE_PATH.write_text(json.dumps(apis, ensure_ascii=False), encoding="utf-8")
    return apis
Confidence
87% confidence
Finding
CACHE_PATH is also sourced from an environment variable and written without path validation. If an attacker can influence environment variables for the process, they can cause the tool to overwrite arbitrary files writable by the current user, which can lead to local file clobbering or corruption.

Tainted flow: 'req' from os.getenv (line 110, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
url = BASE_URL + HEALTH_PATH + separator + urllib.parse.urlencode({"sort": "hot"})
    try:
        req = urllib.request.Request(url, headers={"Accept": "application/json"})
        with urllib.request.urlopen(req, timeout=12) as resp:
            payload = json.loads(resp.read().decode("utf-8", errors="ignore"))
    except Exception:
        return {}
Confidence
95% confidence
Finding
The request URL is built from BASE_URL and HEALTH_PATH, both environment-controlled, and then fetched over the network. This creates an SSRF-style capability or at least arbitrary outbound request behavior if an attacker can influence environment variables, allowing connections to internal services or attacker-controlled hosts and poisoning the discovered API list.

Tainted flow: 'req' from os.getenv (line 110, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
req = urllib.request.Request(url, data=data, headers=headers, method=method)
    try:
        with urllib.request.urlopen(req, timeout=15) as resp:
            raw = resp.read()
            ctype = (resp.headers.get("Content-Type") or "").lower()
            if "application/json" in ctype:
Confidence
96% confidence
Finding
API calls are sent to a URL derived from BASE_URL plus paths discovered from a remotely fetched health endpoint. If BASE_URL or the discovery response is attacker-controlled, the client can be induced to send requests, including the X-API-Key header, to malicious or internal destinations. That makes this more dangerous than a generic outbound request because it can leak credentials and enable SSRF-like access patterns.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The script stores the API key in a local JSON config file by default and does not warn the user that a plaintext secret is being persisted. In shared environments or on systems with weak file permissions, this can expose credentials to other local users or backups/logging processes.

Static analysis

No suspicious patterns detected.