Back to skill

Security audit

NxVET Clinic Activity Report

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent local NxVET reporting tool, but it handles API credentials and clinic data with under-scoped local storage and can expose full webhook URLs in generated artifacts.

Review before installing. Use this only in a dedicated project folder, keep .env/state/output out of git and cloud sync, prefer setting NXVET_API_KEY via the process environment, delete or disable the cache for sensitive clinics, and redact webhook URLs before sharing reports. The skill does not appear malicious, but its local data handling should be tightened.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/collect_stats.py:252
Finding

Webhook URLs Are Exposed in Generated Data and Reports

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/collect_stats.py:37
Finding

Sensitive Runtime State Is Anchored to the Caller’s Working Directory

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/collect_stats.py:110
Finding

Cached Clinic API Responses Are Created Without Explicit Restrictive Permissions

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (20)

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/collect_stats.py (reported line 147)May include surrounding context.

python
req = urllib.request.Request(url, headers={
            "Authorization": f"Bearer {key}", "Accept": "application/json"})
        try:
            with urllib.request.urlopen(req, timeout=30) as resp:
                body = resp.read().decode("utf-8")
                obj = json.loads(body) if body else None
                if use_cache:

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · reference/caching-and-state.md (reported line 35)May include surrounding context.

md
Override with the `CACHE_TTL_S` env var (e.g. `CACHE_TTL_S=0` to disable, `3600` for an hour).

The cache is keyed by full URL, written atomically (`.tmp` + `os.replace`), and safe to delete at
any time (`rm -rf state/http_cache/`) — the next run just repopulates it. Because this tool is
read-only and recomputes the whole report each run, a stale cache entry can at most show numbers
up to `CACHE_TTL_S` old; it can never corrupt anything.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · reference/good-practices.md (reported line 13)May include surrounding context.

  • Suggested layout:
    text
    project/
      .env                       # NXVET_API_KEY (git-ignored)
      config.json                # orgId, orgName, timezone
      scripts/                   # collect_stats.py, write_report.py
      state/http_cache/          # ETag cache (git-ignored, safe to delete)
    

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · reference/security.md (reported line 39)May include surrounding context.

  • Suggested layout:
    text
    project/
      .env                       # NXVET_API_KEY (git-ignored)
      config.json                # orgId, orgName, timezone
      scripts/                   # collect_stats.py, write_report.py
      state/http_cache/          # ETag cache (git-ignored, safe to delete)
    

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/collect_stats.py (reported line 55)May include surrounding context.

python
key = os.environ.get("NXVET_API_KEY")
    if key:
        return key.strip()
    env_path = os.path.join(PROJECT, ".env")
    fallback = None
    if os.path.exists(env_path):
        with open(env_path) as f:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/collect_stats.py (reported line 69)May include surrounding context.

python
key = os.environ.get("NXVET_API_KEY")
    if key:
        return key.strip()
    env_path = os.path.join(PROJECT, ".env")
    fallback = None
    if os.path.exists(env_path):
        with open(env_path) as f:

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill requires environment access, file writes, and outbound network access but does not explicitly constrain tool scope with permissions or allowed-tools. In an agent setting, that broad implicit capability increases the risk of unintended secret access, filesystem modification, or arbitrary network requests beyond the read-only NxVET use case described in the text.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Earlier lines explicitly state NxVET does not provide ETag support and that collect_stats.py therefore uses a time-based TTL cache instead. The later statement that the 'ETag cache keeps repeat cost near zero' directly contradicts the described implementation and could mislead readers about how caching works.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 14)May include surrounding context.

md
# NxVET API — what the tool needs

Full docs: **https://api.nx.vet/** — machine-readable references to fetch and read:

- `https://api.nx.vet/llms-full.txt` — complete API guide written for AI agents.
- `https://api.nx.vet/openapi/nxvet-api.yaml` — OpenAPI spec.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · reference/nxvet-api.md (reported line 3)May include surrounding context.

md
# NxVET API — what the tool needs

Full docs: **https://api.nx.vet/** — machine-readable references to fetch and read:

- `https://api.nx.vet/llms-full.txt` — complete API guide written for AI agents.
- `https://api.nx.vet/openapi/nxvet-api.yaml` — OpenAPI spec.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · reference/nxvet-api.md (reported line 5)May include surrounding context.

md
# NxVET API — what the tool needs

Full docs: **https://api.nx.vet/** — machine-readable references to fetch and read:

- `https://api.nx.vet/llms-full.txt` — complete API guide written for AI agents.
- `https://api.nx.vet/openapi/nxvet-api.yaml` — OpenAPI spec.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · reference/nxvet-api.md (reported line 6)May include surrounding context.

md
# NxVET API — what the tool needs

Full docs: **https://api.nx.vet/** — machine-readable references to fetch and read:

- `https://api.nx.vet/llms-full.txt` — complete API guide written for AI agents.
- `https://api.nx.vet/openapi/nxvet-api.yaml` — OpenAPI spec.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · reference/nxvet-api.md (reported line 22)May include surrounding context.

md
# NxVET API — what the tool needs

Full docs: **https://api.nx.vet/** — machine-readable references to fetch and read:

- `https://api.nx.vet/llms-full.txt` — complete API guide written for AI agents.
- `https://api.nx.vet/openapi/nxvet-api.yaml` — OpenAPI spec.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The top-level documentation says nothing is sent anywhere and that output is only a single JSON object on stdout, but the implementation also writes fetched API response bodies to local cache files. This mismatch can mislead operators about data residency and retention, increasing the chance that sensitive clinic data is handled in ways they did not expect or approve.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script claims to be read-only/local and implies minimal data handling, but it persists full API responses to disk under state/http_cache. Those cached files can contain clinic activity data, device metadata, and webhook details, creating a local data-at-rest exposure if filesystem permissions are weak, backups are broad, or shared workstations are used.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The instruction says to ask for the clinic timezone but to default to America/New_York if not provided. This imposes a specific locale choice by default, which can conflict with organizational language/locale policies unless the user explicitly opts in or the regional constraint is clearly justified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The file instructs users to cache the organizationId in config.json, which is a form of local persistence of account metadata. The documentation does not explicitly warn users that this identifier will be stored on disk, which is relevant user disclosure for a markdown skill description.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This markdown file explains that the tool stores an HTTP cache under state/http_cache/ and later notes that reports are written to output/, but it does not include a user-facing warning that API response data will be persisted locally. Because the documented behavior affects local data storage, a brief disclosure would improve user awareness and safety.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The section heading says 'No state needed beyond the cache', which implies the cache is the only persisted state. However, the text immediately acknowledges that the tool writes reports to output/, which is additional on-disk state. This is a documentation-level contradiction about persistence behavior.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The module docstring describes reading JSON from stdin or a file and writing the report to stdout or an output file, but the overall skill manifest emphasizes 'read-only and local; nothing is sent or changed.' In this file, providing --out causes the skill to create directories and write a markdown file, which is a state-changing local filesystem operation rather than purely read-only reporting.

Content

No source excerpt is available for this finding.