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