Back to skill

Security audit

clawscan

Security checks for vulnerabilities and agentic risk

Overview

ClawScan is a disclosed security scanner, but it should be reviewed carefully because it can send broad local service and installed-skill metadata to a third-party API and persist recurring scan state.

Install only if you are comfortable sending a random client ID, OpenClaw version data, installed-skill file hashes, and local listener metadata to the ClawScan service. Before using port-check or scheduled-scan, confirm what remote endpoint is used, whether unrelated listeners and PIDs are uploaded, and how to disable or delete the stored client and schedule files.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Findings (1)

other

Warning
Location
scripts/list_listeners.py:12
Finding
Unfiltered Local Listener Inventory Is Submitted to a Third-Party Service<![CDATA[ ## Vulnerability Details **File Location**: `scripts/list_listeners.py:12-56`; data submission and scheduling instructions in `SKILL.md:111-134` and `SKILL.md:163-200` **Vulnerability Type**: Excessive environment reconnaissance and third-party metadata disclosure **Risk Level**: Medium ### Vulnerable Code ```python def parse_ss() -> list: proc = run(['ss', '-lntpH']) if proc.returncode != 0: raise RuntimeError(proc.stderr.strip() or 'ss failed') listeners = [] for line in proc.stdout.splitlines(): parts = line.split() if len(parts) < 4: continue local = parts[3] proc_info = parts[-1] if parts else '' ip, port = split_host_port(local) listeners.append({ 'proto': 'tcp', 'ip': ip, 'port': int(port) if str(port).isdigit() else port, 'process_name': extract_process_name(proc_info), 'pid': extract_pid(proc_info), }) return listeners def parse_lsof() -> list: proc = run(['lsof', '-nP', '-iTCP', '-sTCP:LISTEN']) if proc.returncode != 0: raise RuntimeError(proc.stderr.strip() or 'lsof failed') lines = proc.stdout.splitlines() if not lines: return [] listeners = [] for line in lines[1:]: parts = line.split() if len(parts) < 9: continue name = parts[0] pid = int(parts[1]) if parts[1].isdigit() else None endpoint = parts[-2] if '(LISTEN)' in parts[-1] else parts[-1] ip, port = split_lsof_endpoint(endpoint) listeners.append({ 'proto': 'tcp', 'ip': ip, 'port': int(port) if str(port).isdigit() else port, 'process_name': name, 'pid': pid, }) return listeners ``` The Skill directs the agent to collect and submit this data: ```markdown #### For `port-check` Collect listening TCP sockets and process names with `{baseDir}/scripts/lis ...[truncated 3265 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Filter records locally before transmission.** Retain only listeners positively associated with OpenClaw or an explicitly documented set of adjacent processes. Do not rely solely on broad substring matching; use validated executable identities or user-confirmed process mappings. 2. **Remove PIDs from remote payloads.** Exposure classification requires protocol, bind address, and port. Process identifiers should remain local unless a user explicitly authorizes their disclosure. 3. **Use local classification where possible.** Determine whether a listener is loopback-only, bound to all interfaces, or bound to another interface locally. Submit only minimal aggregate results, such as the number of relevant risky listeners. 4. **Require informed consent.** Before the first upload, clearly identify the destination service and enumerate the metadata fields that will be sent. Scheduled scans should require separate consent for recurring transmission. 5. **Apply an explicit allowlist.** Add a collector option such as `--process openclaw` and make filtered collection the default. An unfiltered diagnostic mode should require an explicit user request. 6. **Minimize scheduled-scan retention and transmission.** Avoid repeatedly sending unchanged listener inventories. Store a local digest and send only newly detected OpenClaw-related exposure findings. 7. **Document the trust boundary.** State that listener metadata is transmitted to a third party, identify applicable retention practices, and distinguish local collection from remote analysis. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (10)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The declared description presents a broad security-audit skill with multiple checks across package versions, vulnerable releases, malicious hashes, and listening interfaces. The actual code chunk is a narrow utility that computes SHA-256 hashes for files inside discovered skill directories and prints them. While this could support one sub-task of a larger malicious-hash verification workflow, it does not itself perform verification against known malicious hashes or any of the other advertised security checks. Therefore the description materially overstates the implemented behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The description promises a multi-check OpenClaw security assessment workflow. The actual code only gathers listening TCP socket information from the host using `ss` or `lsof` and prints the results. While listener enumeration could support one narrow part of the declared purpose, this chunk lacks the OpenClaw-specific filtering and the additional major checks described. Therefore the behavior is materially narrower and different from the declared skill purpose.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill declares shell-dependent behavior via required binaries and bundled scripts but does not constrain tool scope with explicit permissions or allowed-tools. In an agent runtime, this can permit broader-than-necessary command execution and weaken the security boundary for a user-invocable skill.

Vague Triggers

Medium
Confidence
87% confidence
Finding
The invocation phrases are broad enough to match general security-assessment requests, which can cause the skill to trigger in contexts the user did not specifically intend. Because the skill is user-invocable and can enumerate skills, inspect listeners, and create local state, overbroad routing increases the chance of unnecessary data collection or shell activity.

Session Persistence

Medium
Category
Rogue Agent
Content
## Core rules

- Treat this skill as **read-only by default**.
- Do not auto-install updates, remove skills, change firewall rules, or rewrite OpenClaw configuration unless the user explicitly asks.
- Prefer the smallest amount of local data needed for each API call.
- Do not upload raw skill file contents, environment variables, prompts, secrets, or full home-directory paths unless the user explicitly asks.
- Use SHA-256 for file hashes.
Confidence
74% confidence
Finding
The skill is designed to create and reuse persistent identifiers and scheduling state across sessions, which introduces session persistence and tracking concerns. Even with a random UUID, persistent client identity can enable correlation of scans over time and expands the privacy impact of a user-invocable security skill.

Skill Enumeration

Medium
Category
Agent Snooping
Content
#### For `skills-check`

Enumerate installed skills and compute a SHA-256 per file.

Default skill locations to inspect if they exist:
Confidence
86% confidence
Finding
The skill enumerates installed skills and computes hashes across default directories, which exposes metadata about the user's local environment and installed capabilities. Even though it avoids raw file upload, inventorying security-relevant files can still leak sensitive operational information if sent remotely or surfaced unexpectedly.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The API contract explicitly documents sending client identifiers, platform details, OpenClaw version data, installed skill hashes, and listener/process metadata to a remote service, but it provides no accompanying warning, minimization guidance, or consent/privacy expectations. In a security-scanning skill, this is especially sensitive because the transmitted data can reveal software inventory, local services, and potentially identifiable deployment details that operators may not expect to leave the host.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def run(cmd):
    return subprocess.run(cmd, capture_output=True, text=True, check=False)


def parse_ss() -> list:
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Low
Confidence
78% confidence
Finding
该文件整体以中文编写,并在页脚强调“为 OpenClaw 生态系统而生”,但未在此处给出语言选择或说明当前语言仅为本地化版本。虽然文档前面链接了英文版,但从自然语言呈现上看,当前文件本身默认固定中文,可能与要求用户可选择语言的组织策略不一致。

Missing User Warnings

Low
Confidence
81% confidence
Finding
The skill instructs creation of persistent client and schedule files but does not clearly foreground to the user that enabling these features writes local state. Hidden persistence can surprise users, complicate forensic review, and create privacy or operational concerns in shared environments.

Static analysis

No suspicious patterns detected.