Back to skill

Security audit

voiceclaw

Security checks for vulnerabilities and agentic risk

Overview

This voice assistant largely matches its stated purpose, but it can expose a local OpenClaw token through unauthenticated API endpoints or unsafe remote configuration.

Review before installing. Keep the service bound to 127.0.0.1, do not expose port 8788 or set HOST=0.0.0.0 without adding authentication and TLS, and do not point OPENCLAW_GATEWAY_URL or VOICEVOX_URL at untrusted remote services. Prefer an explicit, least-privilege OpenClaw token for this voice assistant, update the Node dependencies, and treat spoken commands and conversation history as data that will be sent to the local server and configured backends.

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

T09 · Insecure Skill Coding Practices

Error
Location
src/server.js:115
Finding

Unauthenticated API Endpoints Act as a Privileged OpenClaw Gateway Proxy

Content
View full analysis
{ if (!OPENCLAW_GATEWAY_TOKEN) { return res.status(500).json({ ok: false, error: 'OPENCLAW_GATEWAY_TOKEN not set' }); } let messages; if (req.body?.messages?.length) { messages = req.body.messages; } else { const text = String(req.body?.text || '').trim(); if (!text) return res.status(400).json({ ok: false, error: 'text or messages required' }); messages = [{ role: 'user', content: text }]; } // SSE headers res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); res.flushHeaders(); const sendEvent = (obj) => res.write(`data: ${JSON.stringify(obj)}\n\n`); try { const upstream = await fetch(`${OPENCLAW_GATEWAY_URL}/v1/chat/completions`, { method: 'POST', headers: { 'Authorization': `Bearer ${OPENCLAW_GATEWAY_TOKEN}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ model: OPENCLAW_MODEL, user: 'voiceclaw', messages, stream: true }), }); ``` The non-streaming endpoint has the same access-control issue: ```js // POST /api/chat { text } → OpenClaw Gateway → { reply } app.post('/api/chat', async (req, res) => { try { if (!OPENCLAW_GATEWAY_TOKEN) { return res.status(500).json({ ok: false, error: 'OPENCLAW_GATEWAY_TOKEN not set' }); } // Accept { messages } (full history) or { text } (single turn) let messages; if (req.b ...[truncated 3780 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/server.js:8
Finding

Auto-Discovered Gateway Token Can Be Transmitted to an Arbitrary or Cleartext Upstream

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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (16)

Credential Access

High
Category
Privilege Escalation
Confidence
91% confidence
Finding

The skill explicitly states that a gateway token is auto-detected from ~/.openclaw/openclaw.json, which means it is designed to read local credential material from a user configuration file. Accessing credentials from a broad, implicit location can expose sensitive tokens to unintended code paths, logs, or downstream services if the skill is compromised or insufficiently sandboxed.

Content

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

md
cd voiceclaw
npm install

# Start (no .env needed if OpenClaw is running locally)
npm start
# → [voiceclaw] OpenClaw config loaded from ~/.openclaw/openclaw.json
# → [voiceclaw] listening on http://127.0.0.1:8788

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
98% confidence
Finding

The lockfile includes path-to-regexp 0.1.12 via Express routing, and this version is associated with a Regular Expression Denial of Service issue. Because this skill provides a voice interface and likely runs an HTTP service with attacker-reachable routes, a crafted request path could consume excessive CPU and disrupt the service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README promotes always-on or wake-word-triggered microphone use and describes sending captured speech to backend services for STT/LLM/TTS processing, but it does not clearly warn users what audio/text is transmitted, retained, or exposed to third-party/local services. In a voice assistant context, this omission can lead to unintentional collection of sensitive spoken data and weak informed consent, especially because the project emphasizes zero-config ease of use.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill documentation describes capabilities that access environment/configuration data and make network requests, but it does not declare any explicit tool scope such as permissions or allowed-tools. This creates an authorization gap where operators may not realize the skill can read local configuration like ~/.openclaw/openclaw.json and communicate with local/remote services, increasing the chance of over-privileged deployment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
79% confidence
Finding

The component table states VOICEVOX is used for 日本語音声合成, which indicates a fixed Japanese output locale. Under SQP-3, forcing a specific language or locale without user opt-in or clear justification is a natural-language policy concern, and this file does not describe any user language choice or region-specific limitation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Automatic discovery of a gateway token from a user config file is credential access behavior, and the documentation presents it as normal startup flow without warning or security considerations. In this skill context, the server mediates requests to the OpenClaw gateway, so silent token ingestion increases the risk of unauthorized use, accidental privilege expansion, or insecure deployment assumptions.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The document explicitly states there are no secrets while also documenting automatic use of a gateway token from ~/.openclaw/openclaw.json. That contradiction can mislead operators and reviewers into underestimating credential handling, causing the token to be accessed, exposed, or logged without appropriate safeguards.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The document declares lang="ja", and the interface strings and default speech-recognition language are fixed to Japanese (ja-JP) without any visible opt-in or language selection. The stated policy flags language or locale constraints when a skill forces a specific language without user choice or explicit justification.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The page sends recognized speech-derived commands and accumulated conversation history to backend endpoints (/api/chat-stream and /api/tts) but the UI does not clearly disclose that spoken content will be transmitted off the browser/session. In a voice-assistant context, users may reasonably assume local handling, so the lack of notice and consent can cause unintended exposure of sensitive spoken data.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The server hard-codes Japanese wake words and defaults speech recognition to ja-JP, which imposes a specific language/locale on users. The file does not present this as an explicit opt-in or offer an in-file language choice, so it conflicts with the policy against forcing a locale without user consent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The configuration table specifies STT_LANG with a default of ja-JP, which indicates a language/locale assumption. Under the policy rule, forcing a specific language is only acceptable when the user is offered a choice or the locale restriction is clearly documented and justified; this file does not provide that justification or explicit opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

This markdown file is written entirely in Japanese and does not indicate that language selection is optional or limited to a Japan-specific audience. Under the policy rule for language/locale constraints, a skill artifact that effectively mandates one language without opt-in can be considered a natural-language policy violation.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: body-parser==1.20.4 — 1 advisory(ies): CVE-2026-12590 (body-parser vulnerable to denial of service when invalid limit value silently di)

Low
Category
Supply Chain
Confidence
86% confidence
Finding

The lockfile pins body-parser 1.20.4, which is reported vulnerable to denial of service when invalid limit handling is triggered. In this file it is a transitive dependency of Express, so the issue is not evidence of malicious behavior, but it can still affect availability if the application exposes request parsing to untrusted clients.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: qs==6.14.2 — 3 advisory(ies): CVE-2026-82417 (qs: Denial of Service via Attacker Controlled isBuffer); CVE-2026-8723 (qs has a remotely triggerable DoS: qs.stringify crashes with TypeError on null/u); CVE-2026-82562 (qs array-limit bypass via bracket-key comma parsing)

Low
Category
Supply Chain
Confidence
80% confidence
Finding

The project locks qs 6.14.2, which has multiple reported denial-of-service and parsing-bypass advisories. Since qs is commonly used for parsing attacker-controlled query strings in Express applications, this can affect availability or input handling correctness if the service accepts untrusted HTTP requests.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 12)May include surrounding context.

json
"start": "node src/server.js"
  },
  "dependencies": {
    "dotenv": "^16.4.5",
    "express": "^4.19.2"
  }
}

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 13)May include surrounding context.

json
},
  "dependencies": {
    "dotenv": "^16.4.5",
    "express": "^4.19.2"
  }
}