Back to skill

Security audit

Ningyao Voice Launcher

Security checks for vulnerabilities and agentic risk

Overview

This looks like a real local Chinese voice-chat launcher, but it exposes sensitive screen/chat data and a browser terminal through weakly protected local APIs.

Install only if you are comfortable running a local web server that can send chat and screen content to the configured model provider. Before use, bind the server to loopback, add per-launch authentication, disable or remove the terminal endpoint, fix the file-read and innerHTML issues, regenerate dependencies from a trusted registry, and keep the API key out of shared folders or version control.

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

T09 · Insecure Skill Coding Practices

Error
Location
assets/voice-chat-local/public/app.js:61
Finding

DOM-Based Cross-Site Scripting in Chat Message Rendering

Content
View full analysis
${role === 'user' ? '你' : '宁姚'}
${content}
`; messagesNode.appendChild(item); item.scrollIntoView({ behavior: 'smooth', block: 'end' }); } ``` ### Technical Analysis The `content` parameter is inserted directly into `item.innerHTML` without HTML escaping or sanitization. The function is used to display both user-controlled messages and model-generated replies. Because model output can be influenced by prompts and may also originate from a configurable OpenAI-compatible endpoint, it must be treated as untrusted. If `content` contains active HTML such as an element with an event handler, the browser parses it as markup rather than displaying it as text. An attacker or compromised model endpoint could therefore return content such as: ```html ``` The exact exfiltration request may be constrained by browser networking policy, but the injected script still executes with the local application's origin and can issue and read same-origin API requests. ### Attack Path 1. The victim opens the local voice-chat interface. 2. The attacker influences a model reply through prompt manipulation, a malicious compatible API endpoint, or compromised upstream output. 3. The response contains attacker-supplied HTML with an executable event handler. 4. `sendMessage()` passes the returned `dat ...[truncated 1080 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
assets/voice-chat-local/server.js:174
Finding

Unauthenticated Local APIs Exposed Without an Explicit Loopback Binding

Content
View full analysis
{ const command = req.body?.command; const matched = matchAllowedCommand(command); if (!matched.ok) { res.status(400).json({ error: 'blocked_command', message: matched.message }); return; } try { const { stdout, stderr } = await execFileAsync(matched.file, matched.args, { cwd: workspaceDir, timeout: 10000, windowsHide: true, maxBuffer: 1024 * 1024 }); res.json({ command: matched.display, mode: matched.mode, stdout: String(stdout || '').trim(), stderr: String(stderr || '').trim() }); } catch (error) { res.status(500).json({ error: 'terminal_failed', message: error.message || '终端执行失败。' }); } }); app.listen(port, () => { console.log(`Voice chat server running at http://localhost:${port}`); }); ``` The same missing access controls apply to the previously registered `/api/chat` and `/api/screen` routes. ### Technical Analysis None of the API routes require authentication, an unguessable session token, or another proof that the caller is the local interactive user. The server also calls `app.listen(port)` without explicitly specifying `127.0.0.1` or `::1`. On typical Node.js installations, omitting the host causes the server to listen on an unspecified address, which can expose it through non-loopback network interfaces. The console message stating that the service is running at `localhost` does not enforce a loopback-only binding. Any host capable of reaching the configured port can therefore directly call the APIs. This includes the terminal endpoint, chat endpoint backed by the user's API key, and image-analysis endpoint. The service also lacks request rate limiting and or ...[truncated 1624 chars]
Remediation
View remediation
{ console.log(`Voice chat server running at http://127.0.0.1:${port}`); }); ``` In addition: 1. Generate an unguessable per-launch session token and require it on every API request. 2. Store the token in an `HttpOnly`, `SameSite=Strict` cookie or pass it through a protected authorization header. 3. Reject unexpected `Host` and `Origin` headers. 4. Add CSRF protection for state-changing endpoints. 5. Apply per-client rate limits and concurrency limits, especially to `/api/chat` and `/api/screen`. 6. Disable the terminal endpoint by default and require explicit opt-in. 7. Configure the operating-system firewall to block remote access to the application port. 8. Return minimal information from `/api/health`. 9. Treat loopback binding as defense in depth rather than a replacement for endpoint authentication. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
assets/voice-chat-local/server.js:56
Finding

Restricted Terminal Allows File Access Outside the Workspace

Content
View full analysis
`. - Wildcards and other `cmd.exe` syntax. The implementation then concatenates the target into a shell command and executes it through `cmd /c`. Although `execFile` is used, invoking `cmd.exe /c` explicitly reintroduces shell parsing. Setting `cwd` does not constrain absolute paths or prevent shell metacharacter interpretation. ### Attack Path 1. An attacker gains access to the terminal endpoint, either through the unauthenticated network service, DOM XSS, or direct local browser access. 2. The attacker submits a command containing an absolute path: ```json { "command": "type C:\\Users\\victim\\.ssh\\config" } ``` 3. T ...[truncated 1277 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
assets/voice-chat-local/package-lock.json:17
Finding

Dependency Lockfile Uses a Non-Official Package Registry Mirror

Content
View full analysis
Remediation
View remediation
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
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
Findings (32)

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 · README.md (reported line 36)May include surrounding context.

md
2. 安装依赖:`cmd /c npm install`
3. 复制配置:`copy .env.example .env`
4. 编辑 `.env`,填入 `OPENAI_API_KEY`
5. 启动:`node --env-file=.env server.js`
6. 打开:`http://localhost:3030`

也可以直接双击:

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 · README.md (reported line 37)May include surrounding context.

md
2. 安装依赖:`cmd /c npm install`
3. 复制配置:`copy .env.example .env`
4. 编辑 `.env`,填入 `OPENAI_API_KEY`
5. 启动:`node --env-file=.env server.js`
6. 打开:`http://localhost:3030`

也可以直接双击:

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 · README.md (reported line 38)May include surrounding context.

md
2. 安装依赖:`cmd /c npm install`
3. 复制配置:`copy .env.example .env`
4. 编辑 `.env`,填入 `OPENAI_API_KEY`
5. 启动:`node --env-file=.env server.js`
6. 打开:`http://localhost:3030`

也可以直接双击:

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 · README.md (reported line 53)May include surrounding context.

md
2. 安装依赖:`cmd /c npm install`
3. 复制配置:`copy .env.example .env`
4. 编辑 `.env`,填入 `OPENAI_API_KEY`
5. 启动:`node --env-file=.env server.js`
6. 打开:`http://localhost:3030`

也可以直接双击:

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 · README.md (reported line 54)May include surrounding context.

md
2. 安装依赖:`cmd /c npm install`
3. 复制配置:`copy .env.example .env`
4. 编辑 `.env`,填入 `OPENAI_API_KEY`
5. 启动:`node --env-file=.env server.js`
6. 打开:`http://localhost:3030`

也可以直接双击:

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 · assets/voice-chat-local/README.md (reported line 20)May include surrounding context.

md
2. 安装依赖:`cmd /c npm install`
3. 复制配置:`copy .env.example .env`
4. 编辑 `.env`,填入 `OPENAI_API_KEY`
5. 启动:`node --env-file=.env server.js`
6. 打开:`http://localhost:3030`

也可以直接双击:

Known Vulnerable Dependency: form-data==4.0.5 — 1 advisory(ies): CVE-2026-12143 (form-data: CRLF injection in form-data via unescaped multipart field names and f)

High
Category
Supply Chain
Confidence
93% confidence
Finding

The project includes form-data 4.0.5, which is flagged for CRLF injection via unescaped multipart field names and filenames. In a voice-chat launcher that may proxy uploads or interact with external APIs, this can enable request smuggling or header/body manipulation when attacker-controlled values are embedded into multipart requests.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: path-to-regexp==0.1.12 — 1 advisory(ies): CVE-2024-45296 (path-to-regexp vulnerable to Regular Expression Denial of Service via multiple r)

High
Category
Supply Chain
Confidence
95% confidence
Finding

path-to-regexp 0.1.12 is a known ReDoS risk, and it is a core routing dependency in Express 4.x. If the application exposes routes influenced by attacker-controlled paths, crafted requests can trigger excessive regex backtracking and tie up the Node.js event loop, causing service degradation or outage.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The README advertises browser voice input, speech output, screen awareness, and configurable remote model endpoints, but it does not explicitly warn that screen content and possibly audio/transcribed content may be sent to the configured API service. In a launcher skill aimed at easy installation, that omission can mislead users into sharing sensitive on-screen or spoken data with third-party endpoints without informed consent.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill describes actions that involve shell execution, dependency installation, environment variable handling, and likely network access, but it does not declare any tool scope or permissions metadata. That omission weakens reviewability and user consent because an agent could invoke higher-risk capabilities than the skill header suggests, increasing the chance of unintended command execution or secret exposure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill instructs users to place an API key into a local .env file but provides no guidance on secret handling, storage risks, or exclusion from logs and version control. In a launcher that also uses install scripts, browser tooling, and local app setup, this creates a realistic path for accidental credential leakage through copied folders, shell history, screenshots, backups, or repository commits.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README says the tool captures microphone input and uses an OpenAI model, but does not clearly disclose that user speech transcripts and prompts may be sent to an external API. In a voice-chat skill, this omission can mislead users into believing the system is fully local, increasing privacy and consent risks for sensitive spoken content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The application sends full conversation history together with the latest screen summary to the chat backend, but this file contains no explicit privacy notice or consent flow for that data transfer. Because the feature combines spoken content with derived screen information, the sensitivity is higher than ordinary chat and can expose personal or confidential context to the server.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The frontend exposes a terminal execution feature in a voice chat launcher and sends raw user-supplied commands to a backend execution endpoint. Even if the backend intends to restrict commands, this UI materially enables command execution in a context where users may not expect shell access, increasing the chance of abuse, prompt-driven misuse, or dangerous backend implementation flaws.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The interface tells the user to enter a 'whitelisted' command, but the code forwards any trimmed string to /api/terminal without enforcing any allowlist on the client. This mismatch is dangerous because it creates a false sense of safety and, if backend validation is weak or bypassable, can lead to arbitrary command execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

User-entered terminal commands are sent to the backend for execution without a strong warning about the risk of running system commands. In this context, users may be induced to execute destructive or sensitive operations, and any backend weakness could turn this into system compromise or data loss.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Speech recognition is hard-coded to zh-CN, and the rest of the UI and voice selection logic are also constrained to Chinese-language operation. This is a locale policy issue because the skill does not appear to offer a language choice or require explicit user opt-in for the forced locale.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

Captured screen frames are periodically converted to images and transmitted to the backend for analysis, but this code provides no explicit warning that images leave the browser for server-side processing. Screen content may contain secrets, personal data, tokens, or confidential documents, so silent or unclear transmission creates a meaningful privacy and data-handling risk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The HTML sets the document language to zh-CN and presents the primary title and onboarding text entirely in Chinese, which imposes a specific language/locale on users. There is no visible opt-in, language switcher, or documented reason that this skill must be Chinese-only.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The HTML explicitly tells users the terminal is 'read-only' and protected by a 'safe whitelist', but this file contains only marketing/descriptive text and no technical enforcement. In a skill that exposes a browser-based terminal launcher, misleading security claims can cause users to trust and invoke terminal features under false assumptions, increasing the chance of unsafe command execution if backend or frontend enforcement is absent or weaker than advertised.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

This server sends user chat history and optional screen-derived context to an external API endpoint by default. In a local voice companion with screen awareness, that can transmit sensitive on-screen content, conversation data, or workspace context off-device, creating privacy and data-handling risk if users are not explicitly informed and consenting.

Content

Scanner excerpt · assets/voice-chat-local/server.js (reported line 16)May include surrounding context.

js
const port = Number(process.env.PORT || 3030);
const model = process.env.OPENAI_MODEL || 'gpt-4.1-mini';
const requestTimeoutMs = Number(process.env.OPENAI_TIMEOUT_MS || 15000);
const baseURL = process.env.OPENAI_BASE_URL || 'https://api.openai.com/v1';
const systemPrompt = process.env.SYSTEM_PROMPT || '你叫宁姚。语气冷静、可靠、有骨气,不油滑,不轻浮。用中文简洁回答,像在和熟悉的人并肩说话。';
const apiKey = process.env.OPENAI_API_KEY;
const client = apiKey ? new OpenAI({ apiKey, baseURL, timeout: requestTimeoutMs }) : null;

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The default system prompt explicitly instructs the model to answer in Chinese, which imposes a fixed language policy on all users. The file does not offer a user opt-in or language selection mechanism, so this is a natural-language locale policy violation under the stated rules.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Both branches of the screen summarization instruction require the model to produce output in Chinese. Because this language constraint is hard-coded and no alternative locale choice is offered, it violates the language/locale policy criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The package description specifies a "Ningyao-style Chinese voice companion," which indicates a language/locale constraint in the skill's natural-language description. There is no accompanying indication that users can choose another language or explicitly opt into Chinese-only behavior.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code obtains an auth token, resolves a registry, and performs an authenticated upload to https://clawhub.ai, which is unrelated to the user-facing function of installing or running a local voice companion. In the context of an end-user skill, authenticated publishing capability is risky because it can misuse existing credentials to publish content remotely without meaningful separation between local setup behavior and maintainer operations.

Content

No source excerpt is available for this finding.