Back to skill

Security audit

Agent Factory

Security checks for vulnerabilities and agentic risk

Overview

This agent-creation skill is mostly purpose-aligned, but it performs persistent OpenClaw configuration changes and contains real input-handling flaws that could let crafted agent names or IDs corrupt files or execute commands.

Install only after review or patching. Expect it to create persistent agent workspaces and modify the global OpenClaw config. Do not let untrusted users or prompts choose agent IDs or names until the sed templating, post-sanitization ID validation, predictable temp file, and hardcoded USER.md identity are fixed.

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)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/create_agent.sh:222
Finding
Command Injection Through Unsafe GNU sed Replacement<![CDATA[ ## Vulnerability Details **File Location**: `scripts/create_agent.sh`, lines 222-225 **Vulnerability Type**: Shell command injection through dynamically constructed GNU sed programs **Risk Level**: High ### Vulnerable Code ```bash # Yer tutucuları değiştir sed -i "s/{AGENT_ID}/${AGENT_ID}/g" "$WORKSPACE_DIR/cron/README.md" sed -i "s/{AGENT_NAME}/${AGENT_NAME}/g" "$WORKSPACE_DIR/cron/README.md" sed -i "s/{AGENT_ID}/${AGENT_ID}/g" "$WORKSPACE_DIR/cron/ornek.py" sed -i "s/{AGENT_NAME}/${AGENT_NAME}/g" "$WORKSPACE_DIR/cron/ornek.py" ``` ### Technical Analysis `AGENT_NAME` is obtained from the `--name` command-line argument and is not validated or escaped before being embedded directly into a double-quoted sed expression. Characters significant to sed—including `/`, `\`, `&`, semicolons, and newline characters—can therefore alter the generated sed program rather than being treated strictly as replacement text. On GNU sed, an attacker who can supply a crafted multiline agent name can terminate the intended substitution and introduce an `e` command. The `e` command executes the resulting text through a shell. Quoting the entire sed expression with shell double quotes does not prevent this because the injection occurs inside sed's command language after shell expansion. The same issue occurs twice for `AGENT_NAME`. `AGENT_ID` is constrained to a smaller character set before these statements, so the directly exploitable input identified here is the unvalidated agent name. ### Attack Path 1. An attacker obtains the ability to invoke `create_agent.sh` or influence the value passed to `--name`. 2. The attacker supplies an agent name containing sed syntax and newline characters crafted to terminate the intended substitution. 3. The shell expands `${AGENT_NAME}` into the sed program. 4. GNU sed parses the injected content as commands rather than literal replacement data. 5. An injected sed `e` command invokes `/bin/sh`. 6. The attacker's command executes wi ...[truncated 575 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not construct sed programs using untrusted data. - Generate the template files directly using a language or API that handles replacements as data rather than executable syntax. - If sed must be retained, rigorously escape replacement metacharacters such as `\`, `&`, and the selected delimiter, and reject newline and control characters. - Apply a conservative allowlist and length limit to agent names. - Prefer a structured template implementation, for example Python string replacement with values passed through environment variables or command-line arguments. - Add regression tests containing slashes, ampersands, backslashes, newlines, and sed command characters. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/create_agent.sh:35
Finding
Post-Sanitization Empty Agent ID Escapes the Intended Agent Workspace<![CDATA[ ## Vulnerability Details **File Location**: `scripts/create_agent.sh`, lines 35-42 and 57-65 **Vulnerability Type**: Improper input validation leading to shared-directory overwrite **Risk Level**: Medium ### Vulnerable Code ```bash # Zorunlu alanları kontrol et if [[ -z "$AGENT_ID" ]] || [[ -z "$AGENT_NAME" ]]; then echo "Hata: --id ve --name zorunludur!" echo "Kullanım: ./create_agent.sh --id 'angarya' --name 'Angarya' --emoji '⚙️' --task 'Görev'" exit 1 fi # ID'yi küçük harfe çevir ve özel karakterleri kaldır AGENT_ID=$(echo "$AGENT_ID" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9_-]//g') # Varsayılan değerler AGENT_EMOJI="${AGENT_EMOJI:-🤖}" AGENT_TASK="${AGENT_TASK:-Kullanıcıya yardımcı olmak}" echo "🤖 Agent Factory - Ajan Oluşturuluyor..." echo " ID: $AGENT_ID" echo " İsim: $AGENT_NAME" echo " Emoji: $AGENT_EMOJI" echo " Görev: $AGENT_TASK" echo "" # Klasör yapısı - sadece ID kullan (id-workspace yerine) WORKSPACE_DIR="/home/ubuntu/.openclaw/agents/${AGENT_ID}" AGENT_DIR="/home/ubuntu/.openclaw/agents/${AGENT_ID}/agent" echo "📁 Klasörler oluşturuluyor..." mkdir -p "$WORKSPACE_DIR/memory" mkdir -p "$WORKSPACE_DIR/sessions" mkdir -p "$WORKSPACE_DIR/skills" mkdir -p "$AGENT_DIR" ``` ### Technical Analysis The script checks whether `AGENT_ID` is empty before normalizing it. It then removes every character outside `[a-z0-9_-]` but does not verify that the result remains nonempty. For example, an input consisting only of periods or other removed characters passes the initial nonempty check and is then transformed into an empty string. Consequently, `WORKSPACE_DIR` resolves to `/home/ubuntu/.openclaw/agents/` rather than a dedicated child directory. Subsequent file-generation operations write `IDENTITY.md`, `SOUL.md`, `USER.md`, `AGENTS.md`, `TOOLS.md`, `MEMORY.md`, `HEARTBEAT.md`, and cron content into the shared agents root. The script also registers an agent with an empty ID in the OpenClaw configuration. ### Attack Path ...[truncated 1178 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Validate the agent ID after normalization, not only before it. - Reject an ID unless it matches a strict expression such as `^[a-z0-9][a-z0-9_-]{0,63}$`. - Fail immediately if the normalized value is empty. - Resolve and validate the final workspace path, ensuring it is a direct child of `/home/ubuntu/.openclaw/agents/` and is not equal to the parent directory. - Reject duplicate IDs unless an explicit, separately authorized update operation is requested. - Avoid silently deleting invalid characters; report invalid input to the caller instead. - Add tests for IDs containing only punctuation, whitespace, Unicode characters, and mixed valid and invalid characters. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/create_agent.sh:234
Finding
Predictable Temporary Configuration File Enables Symlink and Race Attacks<![CDATA[ ## Vulnerability Details **File Location**: `scripts/create_agent.sh`, lines 234-258 **Vulnerability Type**: Insecure predictable temporary file in a shared directory **Risk Level**: Medium ### Vulnerable Code ```bash CONFIG_FILE="/home/ubuntu/.openclaw/openclaw.json" TEMP_FILE="/tmp/openclaw_agent_$$.json" # Yeni ajan object'ini oluştur (tek değişkende) # Not: Model ayarları agents.defaults'tan gelir - buraya gerek yok NEW_AGENT=$(jq -n \ --arg id "$AGENT_ID" \ --arg name "$AGENT_NAME" \ --arg emoji "$AGENT_EMOJI" \ '{ id: $id, name: $name, workspace: ("/home/ubuntu/.openclaw/agents/" + $id), agentDir: ("/home/ubuntu/.openclaw/agents/" + $id + "/agent"), identity: { name: $name, emoji: $emoji } }') # Mevcut config'i al ve yeni ajanı ekle jq --argjson newAgent "$NEW_AGENT" \ '.agents.list += [$newAgent]' \ "$CONFIG_FILE" > "$TEMP_FILE" && mv "$TEMP_FILE" "$CONFIG_FILE" ``` ### Technical Analysis The temporary configuration pathname is derived solely from the process ID and is placed in the globally shared `/tmp` directory. The script does not create the file exclusively, verify its type or ownership, set restrictive permissions, or protect the operation against symbolic links. A local attacker who can predict or observe the process ID may pre-create `/tmp/openclaw_agent_<PID>.json` as a symbolic link. Shell redirection follows that link before `jq` starts, potentially truncating and writing to another file accessible to the Skill's execution user. There is also a time-of-check/time-of-use opportunity around writing and moving the pathname. The script does not install a cleanup trap, and the temporary file may inherit permissions affected by the caller's `umask`. ### Attack Path 1. A local attacker predicts or observes the PID of a forthcoming or running `create_agent.sh` process. 2. The attacker creates the corresponding `/tmp/openclaw_agent_<PID>.json` pathname as a symbolic link to a targ ...[truncated 923 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Create the temporary file using `mktemp` so that it is opened with an unpredictable name and secure creation semantics. - Place temporary configuration files in a private directory owned by the OpenClaw user, preferably on the same filesystem as the final configuration. - Set a restrictive `umask`, such as `umask 077`, before handling configuration data. - Register a trap to remove the temporary file on normal exit, error, or interruption. - Validate the generated JSON before replacement. - Preserve the intended ownership and permissions of `openclaw.json`. - Perform the final replacement atomically from a protected directory. Example pattern: ```bash umask 077 TEMP_FILE=$(mktemp "/home/ubuntu/.openclaw/.openclaw.json.tmp.XXXXXX") trap 'rm -f -- "$TEMP_FILE"' EXIT jq --argjson newAgent "$NEW_AGENT" \ '.agents.list += [$newAgent]' \ "$CONFIG_FILE" > "$TEMP_FILE" jq empty "$TEMP_FILE" mv -- "$TEMP_FILE" "$CONFIG_FILE" trap - EXIT ``` ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill advertises agent creation and switching, but the documentation also reveals privileged side effects: automatic creation of many files and modification of the global OpenClaw configuration. That mismatch is dangerous because users may invoke a seemingly simple management skill without understanding it performs persistent filesystem writes and changes shared runtime state, which can enable persistence, misconfiguration, or unintended agent capabilities.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The skill's natural-language description and usage instructions are presented in Turkish throughout the file, which effectively forces a specific language for users. The file does not offer an alternative language, user opt-in, or a documented reason for a Turkish-only locale constraint.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The create-agent flow states that files are automatically created, but it does not clearly warn that this is a persistent write operation affecting agent state and configuration. In a skill that provisions new agents, hidden persistence is security-relevant because it can surprise operators, complicate auditing, and create attack surface through generated files and config entries.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
The documentation highlights Google Sheets access and cron job creation as available to all generated agents but does not warn that these are write-capable integrations and persistence mechanisms. In this context, granting every new agent spreadsheet modification and scheduled task capability increases the blast radius if an agent is misused or prompted maliciously.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This shell script performs safety-relevant file creation throughout the agent workspace and later modifies the shared configuration file, but it does so immediately once required arguments are present. Although there are progress messages, there is no user confirmation step warning that persistent filesystem and config changes will be made.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script hardcodes a specific person's name into every generated USER.md, causing unnecessary propagation of personal data to all new agent workspaces. This creates privacy risk, can misattribute ownership or identity across agents, and may expose personal information to other users, tools, backups, or logs without consent.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The manifest describes this skill as creating agents and switching between agents. In addition to creating agent files and updating config, the script prepares a dedicated cron directory, generates cron documentation, and creates a sample scheduled task file with instructions to copy it into the global cron area, introducing task-scheduling capability not justified by the stated purpose.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
User-facing comments, usage text, prompts, and generated markdown content are written exclusively in Turkish, which imposes a language choice by default. The file does not indicate that the skill is intentionally restricted to Turkish-speaking users or provide any opt-in language selection.

Intent-Code Divergence

Low
Confidence
77% confidence
Finding
The script writes guidance into SOUL.md that includes 'Dışarıya veri gönderme' as a boundary, which reads as a prohibition on sending data outward. But later it generates TOOLS.md stating the agent is accessed via Telegram and WhatsApp, and HEARTBEAT.md comments mention heartbeat API calls, creating contradictory embedded intent documentation about external communication.

Static analysis

No suspicious patterns detected.