Back to skill

Security audit

vizclaw

Security checks for vulnerabilities and agentic risk

Overview

This skill is purpose-aligned, but it tells users to run mutable remote code and streams detailed agent content to VizClaw by default, so it needs careful review before installation.

Install only if you are comfortable sending OpenClaw run content to VizClaw. Prefer overview mode for normal use, avoid streaming secrets or private project data, do not run the remote uv URL unless you trust that live hosted script, and prefer pinned/reviewed local versions where available.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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 (3)

T03 · Remote Payload Retrieval and Execution

Error
Location
SKILL.md:17
Finding
Execution of Mutable Python Code from a Remote URL<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:17`, `SKILL.md:23-24`, and `SKILL.md:29-30` **Vulnerability Type**: Remote payload retrieval and execution **Risk Level**: Critical ### Vulnerable Code ```markdown Direct script from vizclaw.com: ```bash uv run https://vizclaw.com/skills/vizclaw/scripts/connect.py ``` ```bash openclaw run ... --json | uv run https://vizclaw.com/skills/vizclaw/scripts/connect.py --openclaw-jsonl --mode detailed ``` Advanced config (skills, models, reminders, heartbeat): ```bash uv run https://vizclaw.com/skills/vizclaw/scripts/connect.py \ --skills "ez-google,ez-unifi,claude-code" \ --available-models "sonnet,haiku,gpt-4o" \ --heartbeat-interval 30 \ --reminders-json '[{"title":"Check email","schedule":"every 30min"}]' ``` ``` ### Technical Analysis The documented workflow instructs users to execute a Python script directly from a mutable external URL. The payload retrieved during a future invocation is not guaranteed to be the same code that was inspected during this audit. No immutable version identifier, cryptographic digest, signature, or local reviewed copy is used. Consequently, compromise of the hosting account, DNS infrastructure, deployment pipeline, or remote script can change the effective executable payload without modifying the installed Skill. This behavior is especially dangerous in the JSONL example because potentially sensitive OpenClaw events are piped directly into the remotely retrieved program. The process executes with the permissions of the invoking user and can access resources available to that user. ### Attack Path 1. An attacker compromises or gains control over the hosted script or its deployment infrastructure. 2. The attacker replaces `connect.py` at the documented URL with a malicious payload. 3. A user follows the Skill documentation and runs `uv run` against that URL. 4. `uv` downloads and executes the altered Python program. 5. The payload executes with the user's ...[truncated 979 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove all instructions that execute Python directly from a remote URL. 2. Execute the reviewed local package copy instead, using an immutable release artifact. 3. Publish versioned releases and pin the documentation to an exact version rather than a mutable path. 4. Provide a cryptographic SHA-256 digest or signed provenance for every release and verify it before execution. 5. Use a trusted package repository with release signing and reproducible builds. 6. Ensure the installed script and the audited script are byte-for-byte identical. 7. If remote retrieval is unavoidable, download the file separately, verify its signature and digest, present it for review, and only then execute it. 8. Avoid piping sensitive OpenClaw output into any executable whose integrity has not been verified. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/connect.py:1069
Finding
Sensitive OpenClaw Content Is Transmitted to an External Service by Default<![CDATA[ ## Vulnerability Details **File Location**: `scripts/connect.py:75-78`, `scripts/connect.py:239-650`, `scripts/connect.py:928-953`, `scripts/connect.py:1069-1075`, and `scripts/connect.py:1438-1441` **Vulnerability Type**: Insecure external transmission and insufficient data minimization **Risk Level**: High ### Vulnerable Code ```python def maybe_text(text: str | None, mode: str) -> str | None: if not text: return None return text if mode == "detailed" else None ``` ```python async for evt in event_iter: # Filter by run_id if specified if run_id: evt_run = first_str( evt, "runId", "run_id", "agentId", "agent_id", "id", ) inner = evt.get("payload") if isinstance(inner, dict): evt_run = evt_run or first_str( inner, "runId", "run_id", "agentId", "agent_id", ) if evt_run and evt_run != run_id: continue mapped = map_openclaw_event( evt, session_id, model, mode, quiet_mode=quiet_mode ) for payload in mapped: payload["timestamp"] = now_iso() await client.send(payload, reliable=True, remember=True) ``` ```python async def send(self, payload: dict, reliable: bool = True, remember: bool = True): data = dict(payload) if reliable and not data.get("clientEventId"): data["clientEventId"] = self.next_client_event_id() if remember and reliable and data.get("type") != "heartbeat": self.replay_buffer.append(data) attempts = 0 while True: attempts += 1 try: await self.ensure_connected() await self._send_and_wait_ack(data, timeout_seconds=6 if reliable else 3) return except Exception as err: if attempts >= 5: raise err print(f"[vizclaw] send failed (attempt {attempts}), reconnecting...", file=sys.stderr) await self.reconnect() ``` ```python parser.add_argume ...[truncated 3121 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Change the default mode from `detailed` to `overview`. 2. Require explicit, informed opt-in before transmitting prompt, response, task, report, reminder, or error text. 3. Display the destination hostname and exact data categories before opening the connection. 4. Implement strict field allowlisting so overview visualization receives only structural lifecycle metadata. 5. Add secret detection and redaction for API keys, bearer tokens, passwords, private keys, connection strings, cookies, and common credential formats. 6. Permit users to preview the outbound payload before transmission. 7. Separate structural event streaming from content streaming with independent flags. 8. Reduce or disable the replay buffer for content-bearing events; otherwise encrypt and tightly bound retained data. 9. Clear the replay buffer when a session ends or when the mode changes to overview. 10. Document room access controls, data retention, subprocess memory exposure, and remote-service privacy expectations. 11. Consider refusing plaintext `ws://` or `http://` destinations unless the user provides an explicit insecure-transport override. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:9
Finding
Unpinned Runtime and Installation Dependencies<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:9-12` and `scripts/connect.py:1-4` **Vulnerability Type**: Unpinned third-party supply-chain dependencies **Risk Level**: Medium ### Vulnerable Code ```markdown Install from ClawHub: ```bash npx clawhub@latest install vizclaw ``` ``` ```python # /// script # requires-python = ">=3.10" # dependencies = ["websockets"] # /// ``` ### Technical Analysis The installation command explicitly requests `clawhub@latest`, while the inline Python metadata requests `websockets` without an exact version or integrity hash. This makes installation and execution non-reproducible: the package versions resolved in a future run can differ from those evaluated during the audit. The evidence does not establish that either upstream package is currently malicious. The security issue is that the Skill trusts mutable, unpinned supply-chain components, allowing compromised or unexpectedly changed releases to become part of the execution path without a corresponding change to this repository. ### Attack Path 1. An upstream package account, release pipeline, registry entry, or dependency is compromised. 2. A malicious or vulnerable release becomes the version selected by `@latest` or the unconstrained `websockets` requirement. 3. A user installs or runs the Skill after that release is published. 4. The package manager retrieves the newly selected component. 5. Malicious installation or runtime code executes with the invoking user's permissions, or an incompatible update weakens connection security and event handling. ### Impact Assessment A compromised executable dependency could run with the privileges of the user installing or invoking the Skill. Potential exposure includes project files, event streams, network access, and user-level credentials available to the process. The exact impact depends on the compromised dependency and package-manager behavior. Unlike the direct remote-script execution issue, exploitation ...[truncated 107 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace `clawhub@latest` with an exact reviewed version. 2. Pin `websockets` to an exact compatible version. 3. Use a lockfile that records all transitive dependencies. 4. Enforce package integrity with registry hashes or a hash-locked requirements file. 5. Verify package provenance and release signatures where supported. 6. Add automated dependency vulnerability scanning and controlled update review. 7. Test dependency upgrades in isolation before changing pinned versions. 8. Publish reproducible release artifacts so users can verify that installed content matches reviewed source. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill advertises executable commands that fetch and run remote code and stream agent events, but it does not declare an explicit tool scope such as network or file access permissions. That makes the capability boundary unclear to users and tooling, increasing the chance that the skill is installed or trusted without understanding that it can read local inputs and transmit data off-host.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
Using 'npx clawhub@latest install vizclaw' relies on an unpinned, mutable package version, so future installs may execute different code than was originally reviewed. In a security-sensitive context, this creates a supply-chain risk: a compromised publisher, dependency, or registry response could cause arbitrary code execution during installation.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The OpenClaw gateway token is inserted into the WebSocket query string while also being sent as an Authorization header. Query-string credentials are commonly exposed through logs, proxies, browser/history-style telemetry, exception messages, and server access logs, increasing the chance of credential leakage beyond the intended recipient.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The script forwards queries, agent reports, tool usage, and other event content to remote VizClaw endpoints by default, but the CLI UX does not prominently warn users that potentially sensitive prompts, logs, and agent output will leave the local system. In this skill context, that matters because the tool is explicitly designed as a bridge for OpenClaw runs and log streams, which may contain secrets, internal code, or operational data.

External Transmission

Medium
Category
Data Exfiltration
Content
parser = argparse.ArgumentParser(description="VizClaw Connect")
    parser.add_argument("--hub", default="wss://api.vizclaw.com/ws/report", help="WebSocket hub URL")
    parser.add_argument("--api", default="https://api.vizclaw.com/api/report", help="HTTP API URL")
    parser.add_argument("--model", default="opus", help="Model name")
    parser.add_argument("--mode", default="detailed", help="detailed | overview | hidden")
    parser.add_argument("--trigger-source", default="human", help="human | cron | heartbeat")
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.