Back to skill

Security audit

OpenClaw Agent Orchestrator

Security checks for vulnerabilities and agentic risk

Overview

This skill is meant to create OpenClaw agents, but its creation script can delete/replace paths and copy broad workspace contents without enough validation or warning.

Review before installing. Use only trusted agent IDs and source workspaces, back up OpenClaw state first, and patch the script to validate IDs, enforce that destinations stay under OPENCLAW_HOME/workspaces, avoid default full-workspace cloning, skip sensitive files and symlinks, and require explicit confirmation before overwriting any existing workspace.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/create-agent.sh:13
Finding
Unvalidated Agent Identifier Enables Destructive Path Traversal<![CDATA[ ## Vulnerability Details **File Location**: `scripts/create-agent.sh`, lines 13-19 and 32-40 **Vulnerability Type**: Path traversal leading to arbitrary directory deletion **Risk Level**: High ### Vulnerable Code ```bash AGENT_ID="$1" AGENT_NAME="$2" AGENT_EMOJI="$3" AGENT_THEME="${4:-default}" OPENCLAW_HOME="${OPENCLAW_HOME:-$HOME/.openclaw}" SOURCE_WORKSPACE="${5:-$OPENCLAW_HOME/workspace}" TARGET_WORKSPACE="${OPENCLAW_HOME}/workspaces/${AGENT_ID}" ``` ```python src = Path(sys.argv[1]).expanduser() dst = Path(sys.argv[2]).expanduser() name = sys.argv[3] emoji = sys.argv[4] theme = sys.argv[5] if dst.exists(): shutil.rmtree(dst) dst.mkdir(parents=True, exist_ok=True) ``` ### Technical Analysis The caller-controlled `AGENT_ID` is appended directly to the target workspace path without validating its format or checking the resolved destination. An identifier containing traversal components such as `../` can cause `TARGET_WORKSPACE` to resolve outside `${OPENCLAW_HOME}/workspaces`. The Python code subsequently invokes `shutil.rmtree(dst)` whenever that destination already exists. This recursive deletion occurs before `openclaw agents add` validates or rejects the agent identifier. Consequently, any downstream validation performed by the OpenClaw CLI cannot prevent the filesystem damage. Shell quoting prevents command injection but does not prevent filesystem path traversal. The security issue is the absence of identifier validation and destination containment checks before a destructive operation. ### Attack Path 1. An attacker or untrusted automation supplies an agent identifier containing traversal components, such as `../../target-directory`. 2. The script constructs a path resembling `${OPENCLAW_HOME}/workspaces/../../target-directory`. 3. Python accepts the path without resolving and validating it against the intended workspace root. 4. If the resulting destination exists, `shutil.rmtree(dst)` recursively deletes it. 5. The script creat ...[truncated 759 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict `AGENT_ID` to a conservative identifier format before using it in a path: ```bash if [[ ! "$AGENT_ID" =~ ^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$ ]]; then echo "invalid agent ID" >&2 exit 1 fi ``` 2. Resolve the workspace root and destination to canonical paths, then verify that the destination remains a strict child of the intended root: ```python workspace_root = (Path(os.environ["OPENCLAW_HOME"]).expanduser() / "workspaces").resolve() dst = (workspace_root / sys.argv[2]).resolve() if dst.parent != workspace_root: raise SystemExit("destination escapes the workspace root") ``` 3. Reject identifiers containing path separators, `.` components, or `..` components even if other validation is added. 4. Avoid unconditional recursive deletion. Refuse to overwrite an existing workspace by default, or require a separate explicit replacement flag and confirmation. 5. Perform all path validation before modifying any files and before calling `shutil.rmtree`. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/create-agent.sh:18
Finding
Unrestricted Workspace Cloning Exposes Sensitive Data to Durable Agents<![CDATA[ ## Vulnerability Details **File Location**: `scripts/create-agent.sh`, lines 18-19 and 42-62 **Vulnerability Type**: Excessive data access and cross-agent information exposure **Risk Level**: Medium ### Vulnerable Code ```bash SOURCE_WORKSPACE="${5:-$OPENCLAW_HOME/workspace}" TARGET_WORKSPACE="${OPENCLAW_HOME}/workspaces/${AGENT_ID}" ``` ```python skip_names = {".git", ".DS_Store", "__pycache__"} def ignored(name: str) -> bool: return name.startswith("._") or name.startswith("backup-") or name in skip_names for current_root, dirnames, filenames in os.walk(src, topdown=True, onerror=lambda e: None): current = Path(current_root) rel = current.relative_to(src) target_dir = dst / rel target_dir.mkdir(parents=True, exist_ok=True) dirnames[:] = [name for name in dirnames if not ignored(name)] for filename in filenames: if ignored(filename): continue source_file = current / filename target_file = target_dir / filename try: shutil.copy2(source_file, target_file) except (PermissionError, OSError): continue ``` ### Technical Analysis The script creates a durable agent by recursively copying almost the entire source workspace. Its denylist excludes only `.git`, `.DS_Store`, `__pycache__`, AppleDouble files, and names beginning with `backup-`. This approach does not exclude common sensitive material such as environment files, API keys, credentials, private keys, runtime state, memory files, session artifacts, logs, configuration files, or user documents. It therefore grants the new durable agent access to data that is not necessarily required for agent creation or identity initialization. Additionally, `shutil.copy2` follows symbolic links by default. A symbolic link located inside the source workspace may cause content from its target to be copied into the new workspace, subject to the invoking user's read permissions. The new agent workspace is then ...[truncated 1409 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create an empty workspace by default and copy only files explicitly required for the new agent. 2. Replace the limited denylist with a strict allowlist of approved templates and configuration files. 3. Explicitly exclude sensitive file patterns, including `.env*`, credentials, tokens, private keys, runtime state, session history, logs, memory stores, and local configuration containing secrets. 4. Detect and reject symbolic links during traversal: ```python if source_file.is_symlink(): continue ``` 5. Canonicalize and validate the source path, and restrict it to administrator-approved workspace roots. 6. Require explicit user confirmation before cloning an existing workspace, including a clear list of files that will be copied. 7. Apply restrictive permissions to the destination workspace and copied files. Do not rely on `copy2` metadata preservation as an access-control policy. 8. Scan the selected files for secrets before registering the new workspace as a durable agent. ]]>
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (4)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description emphasizes creating and repairing durable OpenClaw agents, bindings, and runtime state, and preferring verified add flows that actually change live state. The supplied code does not perform any add, repair, update, or other mutating operation. It only queries and prints existing state: agents, bindings, cron jobs, and sessions. That makes the primary purpose materially different: inspection/verification rather than creation/repair. The inclusion of cron inspection is also outside the stated scope, though the larger mismatch is that the code is entirely read-only while the description promises state-changing orchestration behavior.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill instructs the agent to run local scripts and OpenClaw CLI commands that can inspect and modify live runtime state, but it does not declare any explicit tool scope or permission boundaries. In a skill system, missing tool constraints increases the chance that the skill can access file read/write or state-changing capabilities beyond what reviewers and callers expect, enabling unintended execution paths or privilege creep.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script unconditionally deletes the target workspace with `shutil.rmtree(dst)` whenever it already exists, without prompting, backup, or validating that the destination is within an expected safe directory. Because `AGENT_ID` influences the destination path, a mistaken or malformed invocation can destroy an existing agent workspace and all contained state. In this skill context, the script is explicitly designed to make durable live-state changes, which makes silent destructive behavior more dangerous rather than less.

Missing User Warnings

Low
Confidence
82% confidence
Finding
The script invokes openclaw agents add and openclaw agents set-identity, which change local agent state and configuration, but the user is not warned beforehand that the script will register or update an agent. The only nearby message appears after existence has already been checked and does not broadly disclose these modifications.

Static analysis

No suspicious patterns detected.