Back to skill

Security audit

Nimo AI Glasses

Security checks for vulnerabilities and agentic risk

Overview

This skill’s core glasses-to-OpenClaw purpose is coherent, but its pairing and deployment defaults expose sensitive access too broadly for a normal install.

Install only after reviewing and changing the deployment defaults: use a strong unique gateway token, avoid printing secrets, keep the gateway on localhost or behind TLS/VPN/firewall rules, remove linkCode from unauthenticated health output, avoid running the broad cleanup option, and pin any OpenClaw package version used for deployment.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (5)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
index.ts:207
Finding

Unauthenticated Health Endpoint Discloses the Active Pairing Secret

Content
View full analysis
handleHealth(res), }); ``` ### Technical Analysis The active link code is the only credential required by `/nimo/pair` to obtain a session token. However, `/nimo/health` returns that credential to any caller. The project documentation explicitly states that routes using `auth: "plugin"` do not require Gateway authentication because the plugin manages authentication itself. Consequently, the supposed pairing secret is not secret. Single-use rotation does not correct this weakness because an attacker can request the latest code immediately before pairing. The absence of rate limiting or trusted-client binding further facilitates automated exploitation. This violates least privilege because unauthenticated clients receive the credential needed to acquire authenticated AI access. ### Attack Path 1. An attacker identifies a network-reachable OpenClaw Gateway running the plugin. 2. The attacker sends `GET /nimo/health` without credentials. 3. The response reveals the current `linkCode`. 4. The attacker sends `POST /nimo/pair` with the disclosed code. 5. The plugin returns a valid bearer token with a 24-hour lifetime. 6. The attacker uses that token with `/nimo/chat` and `/nimo/events`. 7. The attacker can invoke the configured AI agent and receive its responses until the token expires or the Gateway restarts. ### Im ...[truncated 441 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
deploy.sh:15
Finding

Deployment Uses and Prints a Predictable Default Gateway Credential

Content
View full analysis
/dev/null || true ``` ```bash echo "✅ Token: $GATEWAY_TOKEN" ``` ```bash echo "🔑 Token: $GATEWAY_TOKEN" ``` ### Technical Analysis If the operator does not define `GATEWAY_TOKEN`, the deployment assigns the same publicly known value, `nimo-demo-2026`, to every installation. This is a predictable credential rather than a securely generated secret. The script also prints the full credential twice. Terminal recording, deployment logs, CI output, shell-session capture, or support transcripts may therefore preserve both default and operator-supplied credentials. The risk is amplified because the same script binds the Gateway to the LAN, making successful credential guessing or reuse remotely exploitable from reachable networks. ### Attack Path 1. An operator runs `deploy.sh` without setting `GATEWAY_TOKEN`. 2. The Gateway is configured with `nimo-demo-2026`. 3. The deployment binds the Gateway to the LAN. 4. An attacker discovers the service or knows its address. 5. The attacker authenticates using the published default token. 6. Alternatively, an attacker with access to deployment logs extracts a custom token from the printed output. 7. The attacker accesses Gateway APIs permitted by that credential. ### Impact Assessment A successful attacker may gain Gateway-authenticated access, not merely access to the plugin's session endpoints. The exact downstream privileges depend on the OpenClaw Gateway configuration, but the credential is used for Gateway authentication and is forwarded by the plugin to the chat-completions endpoint. Potential consequences include unauthorized AI-agent ...[truncated 146 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
deploy.sh:54
Finding

Deployment Exposes Sensitive Gateway Traffic over Plaintext LAN HTTP

Content
View full analysis
/dev/null || true ``` ```bash echo "📍 Gateway 地址: http://$(hostname -I 2>/dev/null | awk '{print $1}' || echo 'YOUR_IP'):18789" echo "🔑 Token: $GATEWAY_TOKEN" echo "" echo "📡 Demo API:" echo " POST http://YOUR_IP:18789/v1/chat/completions" echo "" echo "🔌 插件 API:" echo " GET http://YOUR_IP:18789/nimo/health" echo " POST http://YOUR_IP:18789/nimo/pair" echo " POST http://YOUR_IP:18789/nimo/chat" echo " GET http://YOUR_IP:18789/nimo/events" ``` ### Technical Analysis The deployment changes the Gateway binding to `lan` and directs clients to use plaintext `http://` endpoints. This broadens the service from local-only access to network access without providing transport confidentiality. Bearer tokens, pairing values, user prompts derived from voice input, and AI responses may cross the LAN in plaintext. Any attacker capable of observing the local network can potentially capture and replay credentials or read conversations. The exposure exceeds the minimum privilege necessary for configurations where the companion application can use loopback, a trusted tunnel, a VPN, or a TLS-terminating reverse proxy. The unauthenticated pairing-code disclosure further increases the danger of LAN exposure. ### Attack Path 1. An operator runs the deployment script, which binds the Gateway to the LAN. 2. A companion application communicates with the documented `http://` endpoints. 3. An attacker on the same network monitors traffic or directly connects to port 18789. 4. The attacker captures a Gateway token, plugin session token, pairing code, prompt, or response. 5. The attacker replays a captured bearer token against the corresponding endpoint. 6. The attacker invokes the AI ...[truncated 548 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
index.ts:79
Finding

HTTP Request Bodies Are Buffered without Size or Duration Limits

Content
View full analysis
{ return new Promise((resolve, reject) => { const chunks: Buffer[] = []; req.on("data", (chunk: Buffer) => chunks.push(chunk)); req.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8"))); req.on("error", reject); }); } ``` The helper is used before parsing pairing and chat request bodies: ```typescript async function handlePair(req: IncomingMessage, res: ServerResponse): Promise { const raw = await readBody(req); ``` ```typescript const raw = await readBody(req); let body: { text?: string; stream?: boolean }; ``` ### Technical Analysis `readBody` stores every received chunk and concatenates the complete request in memory. It does not enforce a maximum body length, validate `Content-Length`, stop reading after a threshold, or establish a request-body timeout. The pairing endpoint is reachable before plugin session authentication. Therefore, an attacker does not need a valid token to force body buffering. Large requests can consume heap memory, while slow requests can retain connections and buffers for extended periods. Repeated requests can cause excessive memory use, garbage-collection pressure, event-loop degradation, or process termination. ### Attack Path 1. An attacker connects to the network-reachable `/nimo/pair` endpoint. 2. The attacker sends a very large request body or continuously streams data without completing the request. 3. The plugin appends every chunk to an in-memory array. 4. The attacker repeats the request over multiple concurrent connections. 5. Gateway memory and connection re ...[truncated 461 chars]
Remediation
View remediation
{ return new Promise((resolve, reject) => { const chunks: Buffer[] = []; let size = 0; req.on("data", (chunk: Buffer) => { size += chunk.length; if (size > maxBytes) { reject(new Error("Request body too large")); req.destroy(); return; } chunks.push(chunk); }); req.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8"))); req.on("aborted", () => reject(new Error("Request aborted"))); req.on("error", reject); }); } ``` ]]>

T08 · Insecure Dependencies

Warning
Location
deploy.sh:25
Finding

Deployment Installs or Updates an Unpinned Global Package

Content
View full analysis
/dev/null; then echo "OpenClaw 已安装: $(openclaw --version)" echo "正在更新..." npm update -g openclaw 2>/dev/null || npm install -g openclaw else npm install -g openclaw fi ``` ### Technical Analysis The deployment installs or updates the global `openclaw` package without specifying a reviewed version or verifying package integrity. Existing installations are automatically updated, so identical deployment input can execute different upstream code at different times. NPM package installation may execute package lifecycle scripts under the privileges of the user running the deployment. A compromised publisher account, malicious upstream release, registry compromise, or unexpected breaking release could therefore result in unreviewed code execution. No evidence shows that the current upstream package is malicious; the vulnerability is the unsafe and mutable supply-chain process. ### Attack Path 1. An attacker compromises the upstream package, publisher account, or package-distribution path. 2. A malicious or tampered release becomes the version selected by NPM. 3. An operator runs `deploy.sh`. 4. The script installs or updates to the unreviewed release without version confirmation. 5. Package installation or lifecycle scripts execute under the operator's account. 6. The malicious package receives access to files, configuration, environment variables, and network resources available to that account. ### Impact Assessment Successful supply-chain exploitation can provide arbitrary code execution with the privileges of the deployment user. That account is expected to have access to `~/.openclaw`, Gateway credentials, configured model API keys, and plugin files. The script does not require root directly, but global NPM configur ...[truncated 104 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (17)

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script offers to delete the entire $HOME/.openclaw directory, which can remove all existing OpenClaw configuration, plugins, tokens, and local state unrelated to this skill. Although gated behind a prompt, this is still dangerous because it performs broad destructive action beyond what is needed to deploy a glasses plugin and can lead to loss of security settings or service disruption.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
97% confidence
Finding

rm -rf "$HOME/.openclaw" is a destructive command that recursively deletes the user's entire OpenClaw state. Even with a yes/no prompt, this is risky because it can wipe unrelated configurations, credentials, and plugins, and it is disproportionate to the stated purpose of installing a single glasses integration.

Content

Scanner excerpt · deploy.sh (reported line 37)May include surrounding context.

sh
read -p "⚠️  检测到旧配置,是否清除重新开始?(y/N) " -n 1 -r
  echo
  if [[ $REPLY =~ ^[Yy]$ ]]; then
    rm -rf "$HOME/.openclaw"
    echo "✅ 旧配置已清除"
  fi
fi

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The script exposes the gateway on the LAN/public interface and later starts it, but does not clearly warn the operator that this may make AI and plugin endpoints remotely reachable. That omission increases the chance of insecure deployment, especially because the script prints externally usable URLs and a token afterward, normalizing remote access without discussing firewalling, token strength, or endpoint sensitivity.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The pairing flow documents that the current link code is available from GET /nimo/health, but does not warn that this endpoint is unauthenticated and effectively reveals the secret needed for initial enrollment. This omission is dangerous because operators may expose the gateway on a LAN or broader network believing pairing is protected, when in practice any reachable client can self-enroll.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The README states there is 'no unauthenticated access to AI,' but elsewhere documents that GET /nimo/health exposes the current pairing link code without authentication. Because the link code is the credential required to obtain a 24-hour bearer token, any party with network access to the gateway can retrieve the code, pair, and gain access to the chat interface, defeating the intended pairing security model.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · README.md (reported line 252)May include surrounding context.

bash
# Health check
curl http://localhost:18789/nimo/health

# Pair
curl -X POST http://localhost:18789/nimo/pair \

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill exposes networked capabilities and describes operational endpoints for pairing, chat, and SSE streaming, but it does not declare any explicit tool scope such as permissions or allowed-tools. This creates an authorization and review gap: the skill may be granted broader env/network/shell access than users or the platform expect, increasing the risk of unintended network exposure, misuse of local resources, or privilege creep.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script explicitly sets gateway.bind to lan, making the OpenClaw gateway reachable from the public network rather than limiting access to localhost or a narrowly scoped interface. In the context of a smart-glasses integration, broad network exposure unnecessarily expands the attack surface and can expose chat, pairing, and event endpoints to unauthorized parties if the host is internet-accessible.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script persists OPENAI_API_KEY or GEMINI_API_KEY into OpenClaw configuration without explicitly informing the user that provider credentials will be stored locally. This can create credential-handling risk if the config file has weak permissions, is backed up insecurely, or is later exposed through host compromise.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
79% confidence
Finding

This code returns a bearer-style session token to the caller, which is a security-sensitive credential, but there is no accompanying user-facing warning, confirmation, or explanatory notice near the operation. For code-file SQP-2, access to credentials or sensitive tokens should have some visible disclosure unless clearly documented elsewhere in markdown, which is not available in this file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The plugin logs active and rotated pairing codes to console output, which can be accessible to other local users, operators, log collectors, or support systems. Because the pairing code is a live authentication secret, log disclosure can let an attacker pair a device and obtain a valid session token without physical access to the intended trusted display path.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The health endpoint returns the current pairing link code to any caller, effectively bypassing the intended out-of-band pairing step. In this skill’s context, the link code is the sole secret required to obtain a session token, so exposing it on an unauthenticated endpoint allows unauthorized pairing and subsequent access to chat and SSE functions.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The manifest presents this as a skill that connects smart glasses through a companion app. The script also performs system-wide package installation/update of OpenClaw with npm, which is broader host provisioning behavior not reflected in the skill description.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The header comment states a specific privacy/data-flow guarantee: "Glasses → Companion App → OpenClaw Gateway" and "Data does NOT pass through Nimo servers." However, the implementation simply exposes HTTP endpoints and accepts requests from any client presenting the link code or session token, with permissive CORS, without any mechanism that constrains the request source to the Companion App or proves the stated end-to-end path. That makes the comment stronger than what the code actually guarantees.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The default system prompt begins with Chinese instructions, which imposes a specific language/locale in the skill's natural-language behavior without explicit user choice. Although the prompt later says to match the user's language, the hardcoded Chinese-language framing can still be a locale-policy concern because no opt-in or justification is provided.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The top-level comment asserts a strong data-flow guarantee that traffic does not pass through Nimo servers, yet the implementation only exposes local HTTP routes and forwards chat to the local gateway. Nothing in this file verifies the Companion App's network path or technically enforces that Nimo infrastructure is bypassed, so the documentation overstates what the code guarantees.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The skill forwards user-provided text and a system prompt to the gateway via an HTTP request. Although the header comment explains the general data flow, it does not clearly warn users at the operation site that their message content is being sent over a local service connection, which is relevant to privacy expectations.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.env_credential_access, suspicious.prompt_injection_instructions

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
index.ts:117

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
src/index.ts:117

Prompt-injection style instruction pattern detected.

Warn
Code
suspicious.prompt_injection_instructions
Location
SKILL.md:34