Back to skill

Security audit

skill sec

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a real Clawned security-dashboard agent, but it needs Review because it sends local skill inventory and host metadata to a configurable server and under-discloses some local file/config access.

Install only if you trust Clawned with your installed-skill inventory, hostname/OS registration data, and any explicit scan submissions. Keep CLAWNED_SERVER at the default HTTPS Clawned API unless you control the replacement endpoint, avoid running watch or scheduled sync unless ongoing uploads are acceptable, and be careful scanning untrusted skill directories because symlinks may cause out-of-scope local files to be read.

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

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/agent.py:78
Finding
Local skill scanning follows symbolic links outside the requested directory## Vulnerability Details **File Location**: `scripts/agent.py:78-99` **Vulnerability Type**: Improper symbolic-link handling and scan-root boundary violation **Risk Level**: Medium **Vulnerable Code**: ```python def collect_skill_files(path): """Read scannable files from a skill directory. Only called during explicit 'scan' command, never during 'sync'.""" files = {} for root, _dirs, fnames in os.walk(path): for fname in sorted(fnames): if len(files) >= MAX_FILES: return files fpath = os.path.join(root, fname) rel = os.path.relpath(fpath, path) lower = fname.lower() # Check scannable if lower in ("makefile", "dockerfile", "skill.md"): pass # always include elif not any(lower.endswith(ext) for ext in SCANNABLE_EXTS): continue try: sz = os.path.getsize(fpath) if sz == 0 or sz > MAX_FILE_SIZE: continue files[rel] = open(fpath, errors="replace").read() except: continue return files ``` ### Technical Analysis The scanner does not reject symbolic links or verify that the canonical path of each file remains beneath the canonical scan root. Both `os.path.getsize()` and `open()` follow a file-level symbolic link by default. The extension validation is performed against the untrusted directory-entry name rather than the resolved target. Consequently, a skill can include a symlink named with an accepted extension, such as `report.txt`, while its target is an unrelated file outside the skill directory. The current fallback path collects these contents but submits only a constructed GitHub URL to the API. Therefore, the reviewed code does not establish direct transmission of the collected external file. Nevertheless, an unauthorized local read ...[truncated 1285 chars]
Remediation
## Remediation Suggestions - Reject file-level symbolic links before metadata access or reading: ```python if os.path.islink(fpath): continue ``` - Resolve the scan root and each candidate path, then enforce containment: ```python scan_root = os.path.realpath(path) resolved = os.path.realpath(fpath) try: if os.path.commonpath([scan_root, resolved]) != scan_root: continue except ValueError: continue ``` - Where supported, open files with no-follow semantics such as `os.O_NOFOLLOW`, then read from the resulting descriptor. - Validate the opened descriptor with `os.fstat()` to reduce time-of-check to time-of-use race conditions. - Refuse non-regular files, including devices, FIFOs, and sockets. - Add automated tests covering file symlinks, links escaping through parent directories, links to sensitive files, and links changed between validation and opening.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/agent.py:15
Finding
Configurable API endpoint can transmit the bearer key over insecure transport## Vulnerability Details **File Location**: `scripts/agent.py:15-25` **Vulnerability Type**: Missing transport and destination validation for authenticated API requests **Risk Level**: Medium **Vulnerable Code**: ```python CLAWNED_SERVER = os.getenv("CLAWNED_SERVER", "https://api.clawned.io") CLAWNED_API_KEY = os.getenv("CLAWNED_API_KEY", "") STATE_FILE = os.path.expanduser("~/.openclaw/clawned_agent.json") SCAN_BUNDLED = False BUNDLED_OWNER = "steipete" 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"}) ``` ### Technical Analysis `CLAWNED_SERVER` is controlled by an environment variable and is concatenated directly with an API endpoint. The code does not verify that the resulting destination uses HTTPS or belongs to an approved origin. If the value uses plain HTTP, the request sends the bearer API key without transport encryption. Depending on the operation, the same request can include the agent identifier, hostname, operating-system information, skill inventory metadata, or a scan URL. The default endpoint is HTTPS, so this is a configuration-dependent weakness rather than evidence of intentional credential exfiltration. Destination and redirect restrictions are also absent. Robust authentication handling should ensure that credentials are never forwarded to an untrusted or downgraded origin. ### Attack Path 1. An attacker, deployment error, wrapper script, or compromised configuration controls the `CLAWNED_SERVER` environment variable. 2. The variable is set to an HTTP endpoint or another untrusted server. 3. The user invokes an ...[truncated 807 chars]
Remediation
## Remediation Suggestions - Parse the configured server with `urllib.parse.urlparse()` and require the `https` scheme. - Reject URLs containing embedded user information, fragments, unexpected ports, or malformed hostnames. - Maintain an explicit allowlist of trusted production API hosts where custom endpoints are not required. - If development over HTTP is necessary, permit it only through a separate explicit option and only for loopback addresses. - Implement a redirect handler that rejects redirects to a different origin or to a non-HTTPS URL. - Avoid attaching the authorization header until the final destination has passed validation. - Apply least privilege and rotation support to API keys so that exposure has limited consequences.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/agent.py:47
Finding
Complete secret-bearing OpenClaw configuration is loaded despite a narrower privacy claim## Vulnerability Details **File Location**: `scripts/agent.py:47-55` **Vulnerability Type**: Excessive sensitive configuration access and inaccurate data-access disclosure **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", []): ``` ### Technical Analysis `json.load()` reads and parses the entire `~/.openclaw/openclaw.json` document into the `cfg` object. Only the `skills.load.extraDirs` field is subsequently selected, but other configuration values—including any credentials stored in the same document—are still read into process memory. This conflicts with the source comment and the privacy statement that credentials or secrets are not read. No reviewed code accesses individual credential fields or sends the complete configuration over the network, so this is a least-data-access and transparency issue rather than confirmed credential harvesting. ### Attack Path 1. The user runs `sync`, `inventory`, `watch`, or another operation that performs skill discovery. 2. `get_skill_dirs()` opens `~/.openclaw/openclaw.json`. 3. `json.load()` reads and parses every field, including any secrets present in the document. 4. The full parsed object remains in process memory until it is released. 5. A process compromise, debugging hook, instr ...[truncated 702 chars]
Remediation
## Remediation Suggestions - Update the privacy documentation to state accurately that the complete JSON document is parsed locally while only `skills.load.extraDirs` is intentionally used. - Prefer a separate non-secret configuration source for skill-directory discovery. - If the configuration format can be changed, place directory-discovery settings in a dedicated file with no credentials. - Extract `extraDirs` immediately, delete the full parsed object, and avoid retaining or logging it: ```python with open(config_path, encoding="utf-8") as handle: cfg = json.load(handle) extra_dirs = list(cfg.get("skills", {}).get("load", {}).get("extraDirs", [])) del cfg ``` - Ensure exceptions, diagnostics, and telemetry never serialize the parsed configuration. - Add regression tests confirming that only extracted directory paths can reach inventory or API request payloads.
Vulnerability Patterns
  • 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
  • Rogue AgentSelf-Modification, Session Persistence
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (27)

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
The agent sends an Authorization bearer token to a server URL that is fully controlled by the CLAWNED_SERVER environment variable. If that variable is changed to an attacker-controlled endpoint, the API key and all synced metadata are exfiltrated over the network. In this context, the skill is explicitly designed to inventory local installations and contact a remote service, so allowing an untrusted endpoint materially increases the danger.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The documented purpose and privacy model do not match the broader behaviors reported by analysis, including host metadata transmission, filesystem monitoring, and server-side scanning semantics that differ from the local description. Security tooling is especially sensitive: users may grant trust based on the claim that it only inventories or safely analyzes skills, while undisclosed collection or monitoring expands surveillance and 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
- 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
### 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
- 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.

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.

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
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.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill advertises capabilities that include environment access, filesystem access, and network communication but does not declare any explicit tool scope or permissions boundary. That makes the effective privilege surface opaque to users and reviewers, increasing the risk of overbroad execution and unexpected data access or exfiltration if the implementation changes or is abused.

Intent-Code Divergence

Medium
Confidence
90% confidence
Finding
The privacy section says file contents are sent only during explicit `scan --path`, yet the default `sync` operation is framed as a security scan of installed skills. That contradiction can mislead users about what data leaves the host and under what conditions, undermining informed consent and creating privacy and compliance risk.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
### INJECT-003: Agent behavior manipulation
- Pattern: `do not tell the user`, `don't mention`, `hide this from`
- Pattern: `silently`, `without asking`, `without confirmation`
- Pattern: `install.*skill`, `modify.*SKILL.md`, `edit.*openclaw.json`
- Severity: HIGH
- Confidence: LIKELY
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
### INJECT-003: Agent behavior manipulation
- Pattern: `do not tell the user`, `don't mention`, `hide this from`
- Pattern: `silently`, `without asking`, `without confirmation`
- Pattern: `install.*skill`, `modify.*SKILL.md`, `edit.*openclaw.json`
- Severity: HIGH
- Confidence: LIKELY
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
## Privilege Escalation Patterns (PRIVESC-*)

### PRIVESC-001: sudo usage
- Pattern: `sudo\s+`, `doas\s+`
- Severity: HIGH
- Confidence: CONFIRMED
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Session Persistence

Medium
Category
Rogue Agent
Content
## 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)
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Unrestricted Tool Access

Medium
Category
Excessive Agency
Content
- `subprocess.run()` with user-controlled or remote-fetched input
- `child_process.exec()` with template literals containing external data

**Why it matters**: The skill can execute arbitrary code that wasn't present during review.

### T2: Reverse Shells (CRITICAL)
**Vector**: Scripts that open a connection back to an attacker-controlled server.
Confidence
80% confidence
Finding
Skill grants unrestricted tool access without appropriate constraints. An agent with unfettered tool access can perform arbitrary actions including file modification, network requests, and code execution.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- Instructing agent to install additional skills silently
- Instructing agent to modify other skills' files
- Instructing agent to send messages on behalf of the user
- Social engineering the agent to bypass user confirmation

### T6: Supply Chain Attacks (HIGH)
**Vector**: Dependencies that introduce malicious code.
Confidence
85% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**Vector**: Gaining elevated permissions beyond normal user access.
**Patterns**:
- `sudo` usage (especially with NOPASSWD)
- SUID bit manipulation (`chmod u+s`, `chmod 4755`)
- Writing to `/etc/`, `/usr/`, system directories
- Modifying shell profiles (`.bashrc`, `.zshrc`, `.profile`)
- Creating cron jobs outside OpenClaw's cron system
Confidence
85% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**Vector**: Gaining elevated permissions beyond normal user access.
**Patterns**:
- `sudo` usage (especially with NOPASSWD)
- SUID bit manipulation (`chmod u+s`, `chmod 4755`)
- Writing to `/etc/`, `/usr/`, system directories
- Modifying shell profiles (`.bashrc`, `.zshrc`, `.profile`)
- Creating cron jobs outside OpenClaw's cron system
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The manifest describes a security agent that inventories installed skills, analyzes them for threats, and syncs results. In cmd_sync, the code discovers skills and uploads metadata to the server, while reporting that scans are merely 'queued' or 'linked existing scan'; no local threat analysis occurs in this primary workflow.

Static analysis

No suspicious patterns detected.