Back to skill

Security audit

Nightscout-Local

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a read-only Nightscout glucose reader, but it documents an unaudited external script path and leaves sensitive health-data network access too broadly scoped.

Review before installing. Use only the bundled nightscout_read.py path, do not rely on the external current_bg.py shortcut unless you separately trust and inspect that file, and set NIGHTSCOUT_BASE_URL only to your own HTTPS Nightscout site. Because this reads health-related CGM data, avoid exposing the URL or output in shared logs or untrusted environments.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/nightscout_read.py:11
Finding
Unrestricted Nightscout Base URL Enables SSRF and Insecure Transport<![CDATA[ ## Vulnerability Details **File Location**: `scripts/nightscout_read.py`, lines 11-25 **Vulnerability Type**: Server-Side Request Forgery and insecure transport **Risk Level**: High ### Vulnerable Code ```python def get_base_url() -> str: base = (sys.argv[sys.argv.index('--url') + 1] if '--url' in sys.argv and sys.argv.index('--url') + 1 < len(sys.argv) else None) or None if not base: import os base = os.environ.get('NIGHTSCOUT_BASE_URL') if not base: base = DEFAULT_BASE_URL return base.rstrip('/') + '/' def fetch_json(path: str): url = urllib.parse.urljoin(get_base_url(), path) req = urllib.request.Request(url, headers={'User-Agent': 'OpenClaw nightscout-local'}) with urllib.request.urlopen(req, timeout=20) as resp: return json.loads(resp.read().decode('utf-8')) ``` ### Technical Analysis The script accepts the base URL directly from the `--url` command-line argument or the `NIGHTSCOUT_BASE_URL` environment variable and passes the resulting URL to `urllib.request.urlopen`. It does not validate the URL scheme, hostname, resolved IP address, port, or redirect destination. An attacker able to influence either input can direct requests toward loopback, private-network, link-local, or otherwise privileged destinations reachable from the Agent's network context. Although the requested Nightscout API paths are fixed by the selected operation, an internal or attacker-controlled server can expose data at those paths or redirect the request to another destination. Python's default URL handling may follow HTTP redirects, and redirect targets are not revalidated. The script also permits plaintext HTTP. Glucose readings and related medical information can therefore be intercepted or altered by a network-positioned attacker. The returned JSON may be presented as legitimate Nightscout data. The response body is read without a maximum size, allowing a malicious server to return a very large response ...[truncated 1469 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Allow only `https` URLs and reject URLs containing embedded credentials. - Parse the URL with `urllib.parse.urlsplit` and explicitly validate the scheme, hostname, and permitted port. - Resolve the hostname and reject loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 addresses. - Disable automatic redirects or revalidate the scheme, hostname, port, and resolved addresses of every redirect destination. - Consider maintaining an explicit allowlist of approved Nightscout hosts. - Require explicit operator approval before connecting to a newly supplied host. - Apply a strict response-size limit by reading the body incrementally and aborting when the maximum is exceeded. - Validate response content types and expected JSON structures before processing data. - Preserve TLS certificate verification and provide no option to disable it. ]]>

T07 · Tool Hijacking and Spoofing

Warning
Location
SKILL.md:27
Finding
Skill Documentation Invokes an Unbundled External Python Script<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 27-31 **Vulnerability Type**: Untrusted external tool invocation **Risk Level**: Medium ### Vulnerable Code ```markdown Simple command path for later automation/use: ```bash python3 /Users/serveradmin/.openclaw/workspace/scripts/current_bg.py ``` ``` ### Technical Analysis The documented automation command executes `current_bg.py` from an absolute path outside the audited Skill directory. That file is not included in the project and therefore cannot be verified as part of this audit. The external file is a mutable trust dependency. Its implementation may differ from the documented read-only behavior, and an attacker who can create or replace it can cause a legitimate-looking workflow to execute arbitrary Python code. This bypasses the integrity boundary established by auditing only the files shipped with the Skill. ### Attack Path 1. An attacker creates or modifies `/Users/serveradmin/.openclaw/workspace/scripts/current_bg.py`. 2. The Agent or operator follows the documented “simple command path.” 3. The local Python interpreter executes the substituted script. 4. The attacker-controlled code runs with the operating-system permissions, environment variables, filesystem access, and network access of the Agent process. ### Impact Assessment Successful exploitation results in arbitrary Python code execution in the Agent's security context. Depending on that context, the substituted script could access workspace data, environment secrets, local files, or network services and could perform actions inconsistent with the Skill's read-only guardrails. Exploitation requires the attacker to control or replace the external script, or for an unsafe script to already exist at that location. The vulnerable documentation does not itself provide that write capability, but it directs execution across an unaudited and mutable trust boundary. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Remove the external command from the documentation unless the referenced script is required and included in the audited package. - Package all executable code under the Skill directory and invoke it using a repository-relative path. - Avoid hard-coded user-specific absolute paths. - If an external helper is unavoidable, verify its ownership, permissions, canonical path, and cryptographic digest before execution. - Ensure the helper is not writable by less-privileged or untrusted users. - Document the helper as a separate trusted dependency and include its source in the audit scope. - Prefer invoking the already audited `scripts/nightscout_read.py` implementation directly. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (4)

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill invokes Python scripts that use environment variables and outbound network access, but the manifest does not declare any tool scope or allowed-tools restrictions. This creates an authorization gap where an agent may execute the skill with broader capabilities than reviewers expect, increasing the risk of unintended data access or abuse if the referenced scripts are modified or behave unexpectedly.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
This code performs HTTP requests to a configurable Nightscout endpoint and transmits request metadata such as the User-Agent, but there is no confirmation prompt, warning comment, or docstring explaining that remote network access will occur. Because Nightscout data is health-related and the destination can be overridden via CLI or environment variable, a clear disclosure would help users understand the privacy impact.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The instruction requires including timestamps in "America/Los_Angeles," which imposes a specific locale/timezone choice on all users. The file does not indicate that this is optional, user-configurable, or justified as a region-specific tool.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The code fixes all displayed timestamps to America/Los_Angeles, which imposes a specific locale setting regardless of the user's own region or preferences. This is a natural-language/policy concern because the behavior is not presented as optional or justified as region-specific.

Static analysis

No suspicious patterns detected.