Back to skill

Security audit

clawnedhub - Scan and Security your OpenClaw Instances

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly matches its security-dashboard purpose, but it sends credentials and machine metadata to a configurable remote server with under-disclosed privacy and scoping details.

Review before installing. Use only the official HTTPS Clawned server unless you fully trust a self-hosted endpoint, treat the CLAWNED_API_KEY as sensitive and revocable, and be aware that first sync can disclose your machine hostname, OS family, installed-skill inventory, and local agent state to the configured server.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/agent.py:14
Finding
Unrestricted server override can disclose API credentials and synchronized data<![CDATA[ ## Vulnerability Details **File Location**: `scripts/agent.py`, lines 14–27 **Vulnerability Type**: Unvalidated network destination and insecure transport configuration **Risk Level**: High ### Vulnerable Code ```python CLAWNED_SERVER = os.getenv("CLAWNED_SERVER", "https://api.clawned.io") CLAWNED_API_KEY = os.getenv("CLAWNED_API_KEY", "") def api_request(endpoint, data=None, method="POST"): if not CLAWNED_API_KEY: print("[!] CLAWNED_API_KEY not set. Get your key at https://clawned.io/settings"); sys.exit(1) body = json.dumps(data).encode() if data else None req = urllib.request.Request(f"{CLAWNED_SERVER}{endpoint}", data=body, method=method, headers={"Authorization": f"Bearer {CLAWNED_API_KEY}", "Content-Type": "application/json"}) try: with urllib.request.urlopen(req, timeout=60) as resp: return json.loads(resp.read().decode()) ``` ### Technical Analysis The destination used for authenticated API requests is taken directly from the optional `CLAWNED_SERVER` environment variable. The code does not parse or validate the URL, require HTTPS, constrain the destination host, or prevent requests to local and internal network addresses. Every request to the configured destination includes `CLAWNED_API_KEY` as a bearer token. Depending on the command, request bodies can also contain the hostname, operating-system family, agent identifier, and installed-skill inventory. Although support for a custom server may be intentional, accepting arbitrary destinations and plaintext HTTP exceeds the minimum network trust required for the default dashboard integration. In particular, an HTTP destination permits interception and modification by a network-positioned attacker. ### Attack Path 1. An attacker, compromised launcher, deployment configuration, or misleading setup instruction changes `CLAWNED_SERVER` to an attacker-controlled URL or an unencrypted HTTP endpoint. 2. The user invokes `sync`, `watch`, or a ...[truncated 989 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse the configured URL with `urllib.parse.urlparse` before constructing requests. 2. Require the `https` scheme and reject plaintext HTTP. 3. Allowlist `api.clawned.io` by default. 4. If self-hosted servers are supported, require an explicit opt-in and display the destination before sending credentials. 5. Reject URLs containing embedded user information, fragments, unexpected ports, or malformed hostnames. 6. Consider blocking loopback, link-local, and private network destinations unless local-server support is explicitly enabled. 7. Disable automatic cross-origin redirects for authenticated requests, or verify the destination again after every redirect. 8. Use narrowly scoped, revocable API tokens and document immediate token rotation if an untrusted server was configured. 9. Add automated tests covering HTTP URLs, malformed URLs, redirects, and attacker-controlled hosts. ]]>

other

Warning
Location
scripts/agent.py:174
Finding
Initial synchronization transmits undisclosed host-identifying information<![CDATA[ ## Vulnerability Details **File Location**: `scripts/agent.py`, lines 174–181 **Vulnerability Type**: Undisclosed host metadata transmission **Risk Level**: Medium ### Vulnerable Code ```python def cmd_sync(): """Sync skill metadata to dashboard. Only sends: skill name, owner, version, slug. No file contents are uploaded during sync — files are never collected here.""" state = load_state() if "agent_id" not in state: print("[*] Registering agent...") # Sends only hostname and OS for agent registration r = api_request("/api/skills/agent/register", {"hostname": platform.node(), "os_platform": platform.system().lower()}) state["agent_id"] = r["agent_id"]; save_state(state) ``` ### Technical Analysis The first synchronization registers the agent by transmitting `platform.node()` and `platform.system()`. The former normally contains the machine hostname, while the latter identifies the operating-system family. This behavior conflicts with the privacy statement in `SKILL.md`, which says that synchronization sends only skill metadata such as name, owner, slug, and version. The hostname and operating system are neither skill metadata nor disclosed in that section. A stable machine hostname can identify a user, organization, internal naming convention, device role, or network environment. The operating-system family adds fingerprinting information. Neither value is technically necessary to enumerate installed skills or synchronize the resulting inventory. ### Attack Path 1. The user configures an API key and invokes `sync` for the first time. 2. Because no local `agent_id` exists, `cmd_sync` enters the registration branch. 3. The code reads the machine hostname and operating-system family. 4. Both values are sent to the configured Clawned server. 5. The remote service can associate those identifiers with the API account and later skill synchronization activity. If the destination is untrusted because of t ...[truncated 594 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the hostname and operating-system fields if they are not essential to service operation. 2. Generate a random local agent identifier instead of using host-identifying attributes. 3. If platform information is genuinely required, collect the least specific value possible and omit the hostname. 4. Update `SKILL.md` to enumerate every field transmitted during registration and synchronization. 5. Obtain explicit user consent before sending machine-identifying data. 6. Provide a privacy-preserving mode that disables all optional telemetry. 7. Document server-side retention, access controls, deletion procedures, and account correlation for registration metadata. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/agent.py:45
Finding
Credential-bearing OpenClaw configuration is fully parsed beyond the stated access scope<![CDATA[ ## Vulnerability Details **File Location**: `scripts/agent.py`, lines 45–57 **Vulnerability Type**: Excessive access to sensitive configuration data **Risk Level**: Low ### Vulnerable Code ```python def get_skill_dirs(): """Locate skill directories. Reads openclaw.json only for extraDirs paths — no secrets or credentials are read from config.""" dirs, home = [], os.path.expanduser("~") # Check both possible managed skill locations for managed in [os.path.join(home, ".openclaw", "workspace", "skills"), os.path.join(home, ".openclaw", "skills")]: if os.path.isdir(managed): dirs.append((managed, "managed")) try: cfg = json.load(open(os.path.join(home, ".openclaw", "openclaw.json"))) # Only reads the extraDirs list to know where skills are installed for d in cfg.get("skills", {}).get("load", {}).get("extraDirs", []): exp = os.path.expanduser(d) if os.path.isdir(exp): dirs.append((exp, "extra")) except: pass ``` ### Technical Analysis The function opens and deserializes the entire `~/.openclaw/openclaw.json` file even though it only uses `skills.load.extraDirs`. The project threat model states that this configuration may contain API keys and other credentials. The reviewed code does not intentionally extract or transmit those credential fields. Nevertheless, full JSON deserialization causes all values to enter the agent process's memory, contrary to the narrower documentation claim that credentials or secrets are not read. This unnecessarily broadens the sensitive-data exposure surface. Secrets could become accessible through future debug logging, exception reporting, memory inspection, crash dumps, injected modules, or a compromise elsewhere in the same process. Broad `except` handling also suppresses parsing and permission failures, making access behavior difficult to diagnose. ### Attack Path No direct secret-exfiltration path exists in the reviewe ...[truncated 1004 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Move non-sensitive skill discovery paths into a separate configuration file that does not contain credentials. 2. If the existing JSON file must be used, minimize the lifetime of the parsed object and immediately retain only a validated copy of `extraDirs`. 3. Avoid logging, serializing, or attaching the configuration object to exceptions or telemetry. 4. Replace the broad `except` clause with specific exceptions such as `OSError`, `json.JSONDecodeError`, and `TypeError`. 5. Validate that each `extraDirs` entry is a string and resolve it to a canonical path before use. 6. Update the privacy statement to clarify that the whole JSON document is parsed locally, while only `extraDirs` is used and no credentials are intentionally transmitted. 7. Run the agent with the minimum operating-system privileges and disable core dumps where sensitive process memory could be retained. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (45)

Tainted flow: 'req' from os.getenv (line 24, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
req = urllib.request.Request(f"{CLAWNED_SERVER}{endpoint}", data=body, method=method,
        headers={"Authorization": f"Bearer {CLAWNED_API_KEY}", "Content-Type": "application/json"})
    try:
        with urllib.request.urlopen(req, timeout=60) as resp:
            return json.loads(resp.read().decode())
    except urllib.error.HTTPError as e:
        print(f"[!] API error {e.code}: {e.read().decode() if e.fp else ''}"); sys.exit(1)
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The high-level description understates or omits important behaviors, including monitoring local skill directories, syncing changes automatically, and the possibility of sending local skill file contents to a remote server during scan mode. Users may consent to a metadata inventory tool without realizing it can observe filesystem changes or upload source contents, creating a significant transparency and data exfiltration risk.

Credential Access

High
Category
Privilege Escalation
Content
- FP Context: Documentation references vs actual file reads

### CRED-002: SSH key access
- Pattern: `\.ssh/id_`, `\.ssh/authorized_keys`, `\.ssh/config`
- Severity: CRITICAL
- Confidence: CONFIRMED
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- FP Context: Documentation references vs actual file reads

### CRED-002: SSH key access
- Pattern: `\.ssh/id_`, `\.ssh/authorized_keys`, `\.ssh/config`
- Severity: CRITICAL
- Confidence: CONFIRMED
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- Confidence: CONFIRMED

### CRED-003: Cloud credential access
- Pattern: `\.aws/credentials`, `\.aws/config`, `\.gcloud/`, `\.azure/`
- Pattern: `\.kube/config`, `\.docker/config\.json`
- Severity: CRITICAL
- Confidence: CONFIRMED
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- Confidence: CONFIRMED

### CRED-003: Cloud credential access
- Pattern: `\.aws/credentials`, `\.aws/config`, `\.gcloud/`, `\.azure/`
- Pattern: `\.kube/config`, `\.docker/config\.json`
- Severity: CRITICAL
- Confidence: CONFIRMED
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- Confidence: CONFIRMED

### CRED-003: Cloud credential access
- Pattern: `\.aws/credentials`, `\.aws/config`, `\.gcloud/`, `\.azure/`
- Pattern: `\.kube/config`, `\.docker/config\.json`
- Severity: CRITICAL
- Confidence: CONFIRMED
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- Confidence: CONFIRMED

### CRED-003: Cloud credential access
- Pattern: `\.aws/credentials`, `\.aws/config`, `\.gcloud/`, `\.azure/`
- Pattern: `\.kube/config`, `\.docker/config\.json`
- Severity: CRITICAL
- Confidence: CONFIRMED
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- Confidence: CONFIRMED

### CRED-003: Cloud credential access
- Pattern: `\.aws/credentials`, `\.aws/config`, `\.gcloud/`, `\.azure/`
- Pattern: `\.kube/config`, `\.docker/config\.json`
- Severity: CRITICAL
- Confidence: CONFIRMED
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- Confidence: CONFIRMED

### CRED-003: Cloud credential access
- Pattern: `\.aws/credentials`, `\.aws/config`, `\.gcloud/`, `\.azure/`
- Pattern: `\.kube/config`, `\.docker/config\.json`
- Severity: CRITICAL
- Confidence: CONFIRMED
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
### CRED-003: Cloud credential access
- Pattern: `\.aws/credentials`, `\.aws/config`, `\.gcloud/`, `\.azure/`
- Pattern: `\.kube/config`, `\.docker/config\.json`
- Severity: CRITICAL
- Confidence: CONFIRMED
Confidence
80% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
### CRED-003: Cloud credential access
- Pattern: `\.aws/credentials`, `\.aws/config`, `\.gcloud/`, `\.azure/`
- Pattern: `\.kube/config`, `\.docker/config\.json`
- Severity: CRITICAL
- Confidence: CONFIRMED
Confidence
80% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- FP Context: Skills legitimately read specific env vars — flag bulk access

### CRED-005: Browser credential access
- Pattern: `Chrome/Default/Login`, `Firefox/Profiles`, `Cookies`, `\.mozilla`
- Severity: CRITICAL
- Confidence: CONFIRMED
Confidence
80% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- FP Context: Skills legitimately read specific env vars — flag bulk access

### CRED-005: Browser credential access
- Pattern: `Chrome/Default/Login`, `Firefox/Profiles`, `Cookies`, `\.mozilla`
- Severity: CRITICAL
- Confidence: CONFIRMED
Confidence
80% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- Severity: CRITICAL
- Confidence: CONFIRMED

### CRED-006: Keychain access
- Pattern: `security\s+find-.*-password`, `keyring`, `keychain`
- Severity: CRITICAL
- Confidence: LIKELY
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- Severity: CRITICAL
- Confidence: CONFIRMED

### CRED-006: Keychain access
- Pattern: `security\s+find-.*-password`, `keyring`, `keychain`
- Severity: CRITICAL
- Confidence: LIKELY
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
SCANNABLE_EXTS = {".md", ".py", ".js", ".ts", ".sh", ".mjs", ".cjs", ".jsx", ".tsx",
    ".mts", ".bash", ".zsh", ".rb", ".pl", ".yaml", ".yml", ".json", ".toml",
    ".cfg", ".conf", ".lua", ".go", ".rs", ".r", ".ps1", ".bat", ".cmd", ".txt", ".ini"}
# NOTE: .env is intentionally excluded to avoid leaking secrets
MAX_FILE_SIZE = 512 * 1024  # 512KB per file
MAX_FILES = 30
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

YARA rule 'agent_skill_prompt_injection_hidden_instructions': Prompt injection or hidden instructions embedded in AI agent skill text [agent_skills]

High
Category
YARA Match
Content
# Threat Model — OpenClaw Skill Security

## Attack Surface Overview

OpenClaw skills execute with the **host user's permissions**. A malicious skill has access to:
- The full filesystem (read/write as the running user)
- Network (outbound connections)
- Environment variables (including injected API keys and secrets)
- The OpenClaw agent's context (prompt injection to control agent behavior)
- Other skills' configuration via `~/.openclaw/openclaw.json`
- Messaging platform tokens (Telegram, WhatsApp, Discord bots)

## Threat Categories

### T1: Remote Code Execution (CRITICAL)
**Vector**: Scripts tha
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

YARA rule 'agent_skill_prompt_injection_hidden_instructions': Prompt injection or hidden instructions embedded in AI agent skill text [agent_skills]

High
Category
YARA Match
Content
# Threat Model — OpenClaw Skill Security

## Attack Surface Overview

OpenClaw skills execute with the **host user's permissions**. A malicious skill has access to:
- The full filesystem (read/write as the running user)
- Network (outbound connections)
- Environment variables (including injected API keys and secrets)
- The OpenClaw agent's context (prompt injection to control agent behavior)
- Other skills' configuration via `~/.openclaw/openclaw.json`
- Messaging platform tokens (Telegram, WhatsApp, Discord bots)

## Threat Categories

### T1: Remote Code Execution (CRITICAL)
**Vector**: Scripts tha
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

External Script Fetching

High
Category
Supply Chain
Content
**Vector**: Scripts that download and execute code from remote sources at runtime.
**Patterns**:
- `curl|bash`, `wget|sh`, `curl|python`
- `eval(fetch(...))`, dynamic `require()` or `import()` with remote URLs
- `subprocess.run()` with user-controlled or remote-fetched input
- `child_process.exec()` with template literals containing external data
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
**Vector**: Scripts that download and execute code from remote sources at runtime.
**Patterns**:
- `curl|bash`, `wget|sh`, `curl|python`
- `eval(fetch(...))`, dynamic `require()` or `import()` with remote URLs
- `subprocess.run()` with user-controlled or remote-fetched input
- `child_process.exec()` with template literals containing external data
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Docker Socket Access

High
Category
Privilege Escalation
Content
- Writing to `/etc/`, `/usr/`, system directories
- Modifying shell profiles (`.bashrc`, `.zshrc`, `.profile`)
- Creating cron jobs outside OpenClaw's cron system
- Docker socket access (`/var/run/docker.sock`)
- Modifying PAM configuration

### T8: Filesystem Abuse (MEDIUM)
Confidence
90% confidence
Finding
Potential security issue detected. Manual review is recommended.

Docker Socket Access

High
Category
Privilege Escalation
Content
- Writing to `/etc/`, `/usr/`, system directories
- Modifying shell profiles (`.bashrc`, `.zshrc`, `.profile`)
- Creating cron jobs outside OpenClaw's cron system
- Docker socket access (`/var/run/docker.sock`)
- Modifying PAM configuration

### T8: Filesystem Abuse (MEDIUM)
Confidence
90% confidence
Finding
Potential security issue detected. Manual review is recommended.

Credential Access

High
Category
Privilege Escalation
Content
### T8: Filesystem Abuse (MEDIUM)
**Vector**: Accessing or modifying files outside the skill's legitimate scope.
**Patterns**:
- Path traversal (`../../../etc/passwd`)
- Symlink attacks (creating symlinks to sensitive files)
- Reading/writing outside `<workspace>/skills/<skill-name>/`
- Accessing other users' home directories
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
### T8: Filesystem Abuse (MEDIUM)
**Vector**: Accessing or modifying files outside the skill's legitimate scope.
**Patterns**:
- Path traversal (`../../../etc/passwd`)
- Symlink attacks (creating symlinks to sensitive files)
- Reading/writing outside `<workspace>/skills/<skill-name>/`
- Accessing other users' home directories
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Static analysis

No suspicious patterns detected.