Back to skill

Security audit

ClawVoice

Security checks for vulnerabilities and agentic risk

Overview

This skill openly acts as a voice bridge, but its agent mode can let a WebSocket endpoint drive the main agent and receive its full output with limited safeguards.

Install only if you trust the voice server and understand that voice messages and agent replies travel through the WebSocket. Avoid pointing `--url` at remote or shared endpoints unless transport and peer trust are handled externally, and prefer running agent mode with a timeout and a limited agent profile.

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

T09 · Insecure Skill Coding Practices

Warning
Location
client.py:61
Finding

Unauthenticated WebSocket Messages Are Delegated to the Main Agent

Content
View full analysis

Vulnerability Details

File Location: client.py:61-68
Related Documentation: skill.md:56-70, skill.md:74-80
Vulnerability Type: Untrusted input delegated across a privileged agent trust boundary
Risk Level: Medium

Vulnerable Code

python
async def cmd_agent(url: str, timeout: float) -> None:
    """Listen for user messages, forward each to openclaw agent, send the response back."""
    async with aiohttp.ClientSession() as session:
        async with session.ws_connect(url) as ws:
            try:
                async with asyncio.timeout(timeout):
                    async for msg in ws:
                        if msg.type == aiohttp.WSMsgType.TEXT:
                            data = json.loads(msg.data)
                            if data.get("type") != "message":
                                continue
                            user_text = data.get("content", "")
                            print(f"[user] {user_text}", flush=True)
                            reply = await run_agent(user_text)
                            print(f"[agent] {reply}", flush=True)
                            await ws.send_json({"type": "message", "content": reply})

The target agent is selected here:

python
async def run_agent(message: str) -> str:
    """Run openclaw agent and return its stdout."""
    cmd = f"openclaw agent --agent main --message {shlex.quote(message)}"
    proc = await asyncio.create_subprocess_shell(
        cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
    )

The endpoint is configurable and defaults to plaintext WebSocket transport:

python
DEFAULT_URL = "ws://localhost:3111/connect"
python
parser.add_argument("--url", default=DEFAULT_URL, help=f"WebSocket URL (default: {DEFAULT_URL})")

Technical Analysis

The agent bridge accepts JSON messages from a WebSocket connection and forwards every message whose type equals message directly to openclaw agent --agent main ...[truncated 2777 chars]

Remediation
View remediation

Remediation Suggestions

  1. Use a dedicated least-privileged agent

    • Replace --agent main with a purpose-built voice agent.
    • Remove unnecessary tools, credentials, filesystem access, and sensitive context.
    • Enforce an explicit allowlist of operations appropriate for voice requests.
  2. Authenticate and authorize the WebSocket peer

    • Require a cryptographically strong session token or mutually authenticated TLS.
    • Validate the peer before accepting any message.
    • Bind authorization to the expected user and session rather than treating every connected server as trusted.
  3. Require protected transport

    • Require wss:// for every non-loopback endpoint.
    • Reject plaintext remote WebSocket URLs.
    • Validate certificates and restrict endpoints to an explicit hostname or URL allowlist.
  4. Apply an agent-input policy boundary

    • Validate that content is a string and enforce strict size limits.
    • Reject unsupported message structures and excessive nesting.
    • Introduce task-specific policy checks before delegating input.
    • Do not rely on shell quoting to defend against prompt-level attacks.
  5. Restrict outbound responses

    • Do not return unrestricted agent output automatically.
    • Detect or redact credentials, secrets, internal paths, and sensitive contextual data.
    • Enforce response-size limits and return structured, task-specific results where possible.
  6. Harden subprocess execution

    • Avoid invoking a shell even though shlex.quote currently mitigates ordinary POSIX shell injection.
    • Use an argument-vector subprocess call such as:
python
proc = await asyncio.create_subprocess_exec(
    "openclaw",
    "agent",
    "--agent",
    "voice-limited",
    "--message",
    message,
    stdout=asyncio.subprocess.PIPE,
    stderr=asyncio.subprocess.PIPE,
)
  1. Add operational safeguards
    • Rate-limit messages and bound agent execution time.
    • Limit concurrent requests.
    • Rec ...[truncated 183 chars]
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
Findings (1)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The agent mode automatically receives user messages over a WebSocket, sends their full content to a local agent process, and transmits the agent's replies back over the network without any user-facing disclosure or consent mechanism. Even if this is expected behavior for a WebSocket client, the absence of warning increases privacy and data-handling risk because users may unknowingly send sensitive prompts or receive sensitive agent output over an unencrypted or unexpected channel.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.