Back to skill

Security audit

Huo15 Openclaw Multi Agent

Security checks for vulnerabilities and agentic risk

Overview

This skill is not clearly malicious, but its multi-agent helper scripts contain unsafe local file and code-execution patterns that users should review before installing.

Install only if you are comfortable reviewing or fixing the shell scripts first. The main risks are unsafe handling of task and worker IDs, persistent logging of task text, and local deletion commands; use simple trusted identifiers only and avoid putting secrets in task descriptions or completion results.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/coordinator.sh:104
Finding

Arbitrary Python Code Execution Through Unsafe Heredoc Interpolation

Content
View full analysis

Vulnerability Details

File Locations:

  • scripts/coordinator.sh:104-120
  • scripts/team.sh:69-94
  • scripts/team.sh:121-146

Vulnerability Type: Python code injection through untrusted command-line arguments
Risk Level: High

Vulnerable Code

scripts/coordinator.sh:104-120:

bash
python3 << PYEOF
import json

config_file = "$TEAM_DIR/config.json"
try:
    with open(config_file, 'r') as f:
        config = json.load(f)
    
    if 'tasks' not in config:
        config['tasks'] = []
    
    config['tasks'].append({
        'taskId': '$task_id',
        'status': 'pending'
    })
    
    with open(config_file, 'w') as f:
        json.dump(config, f, indent=2)
except Exception as e:
    print(f"Update failed: {e}")
PYEOF

scripts/team.sh:69-94:

bash
python3 << PYEOF
import json

team_file = "$TEAM_DIR/team.json"
try:
    with open(team_file, 'r') as f:
        team = json.load(f)
    
    if 'members' not in team:
        team['members'] = []
    
    # Check whether the worker already exists
    exists = any(m.get('workerId') == '$worker_id' for m in team['members'])
    if not exists:
        team['members'].append({
            'workerId': '$worker_id',
            'task': '$task_desc',
            'status': 'running',
            'startedAt': '$(date -u +%Y-%m-%dT%H:%M:%SZ)'
        })
        with open(team_file, 'w') as f:
            json.dump(team, f, indent=2)
        print("Worker added to team")
    else:
        print("Worker already exists: $worker_id")
except Exception as e:
    print(f"Error: {e}")
PYEOF

scripts/team.sh:121-146:

bash
python3 << PYEOF
import json

worker_file = "$worker_file"
result = """$result"""

try:
    with open(worker_file, 'r') as f:
        worker = json.load(f)
    
    worker['status'] = 'completed'
    worker['result'
...[truncated 2918 chars]
Remediation
View remediation

Remediation Suggestions

  • Never generate Python source code by interpolating command-line input.

  • Pass dynamic values as positional arguments:

    bash
    python3 - "$TEAM_DIR/config.json" "$task_id" << 'PYEOF'
    import json
    import sys
    
    config_file = sys.argv[1]
    task_id = sys.argv[2]
    
    with open(config_file, "r", encoding="utf-8") as file:
        config = json.load(file)
    
    config.setdefault("tasks", []).append({
        "taskId": task_id,
        "status": "pending",
    })
    
    with open(config_file, "w", encoding="utf-8") as file:
        json.dump(config, file, indent=2)
    PYEOF
    
  • Quote heredoc delimiters when the body must remain literal.

  • Apply the same sys.argv or environment-variable pattern to worker IDs, descriptions, and results.

  • Use json.dump for every JSON document instead of constructing JSON with shell heredocs.

  • Validate identifiers separately using a strict allowlist such as ^[A-Za-z0-9_-]+$.

  • Return a nonzero exit status when Python state updates fail instead of catching errors and continuing as though the operation succeeded.

  • Add regression tests with single quotes, double quotes, triple quotes, backslashes, newlines, and Python statements in every user-controlled argument.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/coordinator.sh:88
Finding

Path Traversal in Task and Worker Identifiers Permits Writes Outside State Directories

Content
View full analysis

Vulnerability Details

File Locations:

  • scripts/coordinator.sh:88-98
  • scripts/team.sh:52-65

Vulnerability Type: Path traversal and unrestricted filesystem path construction
Risk Level: Medium

Vulnerable Code

scripts/coordinator.sh:88-98:

bash
local task_id="$1"
local task_desc="${2:-}"

if [ -z "$task_id" ]; then
    echo "Usage: coordinator.sh assign task-id description"
    return 1
fi

load_config

mkdir -p "$TEAM_DIR/tasks"
cat > "$TEAM_DIR/tasks/$task_id.json" << EOF

scripts/team.sh:52-65:

bash
local worker_id="$1"
local task_desc="${2:-Unspecified task}"

if [ -z "$worker_id" ]; then
    echo "Usage: team.sh spawn worker-id task-description"
    return 1
fi

echo "Starting worker Agent: $worker_id"
echo "Task: $task_desc"
echo ""

mkdir -p "$TEAM_DIR/workers/$worker_id"
cat > "$TEAM_DIR/workers/$worker_id/worker.json" << EOF

Technical Analysis

User-controlled task_id and worker_id values are used directly as filesystem path components. The scripts only check whether the identifiers are empty; they do not reject directory separators, .. components, absolute paths, or symbolic-link traversal.

Shell quoting prevents word splitting and wildcard expansion, but it does not prevent path traversal. The operating system still resolves sequences such as ../ before opening the destination. Consequently, the final path can escape from the intended task or worker directory.

The task operation appends .json to the attacker-controlled identifier. This constrains the final filename but does not ensure that it remains under TEAM_DIR/tasks. The worker operation creates an attacker-selected directory and writes a fixed worker.json file inside it. Existing symbolic links in writable portions of the path can further redirect these operations.

Attack Path

  1. The attacker invokes `coordinator.sh assign ...[truncated 1533 chars]
Remediation
View remediation

Remediation Suggestions

  • Restrict task and worker identifiers to a conservative allowlist:

    bash
    validate_identifier() {
        case "$1" in
            ""|*[!A-Za-z0-9_-]*)
                echo "Invalid identifier" >&2
                return 1
                ;;
        esac
    }
    
  • Reject absolute paths, directory separators, empty identifiers, . components, and .. components.

  • Resolve both the base directory and candidate destination to canonical paths and verify that the destination starts with the canonical base directory followed by a path separator.

  • Check each existing parent component for symbolic links before writing, or use a secure implementation based on directory file descriptors and no-follow semantics.

  • Create state directories with restrictive permissions, such as mode 0700, and state files with mode 0600.

  • Write to a temporary file created inside the validated destination directory and atomically rename it into place.

  • Avoid using externally supplied identifiers as physical directory names where possible. Generate internal random identifiers and store the external label only as JSON data.

  • Add tests for ../, repeated traversal, absolute paths, slash and backslash separators, symbolic links, and identifiers that normalize outside the approved base directory.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (17)

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding

The description presents this skill as a functional multi-agent parallel work system with coordinator mode, task assignment, and result summarization. However, the supplied script only validates arguments, creates a local log directory, writes a log entry, and prints guidance text. There is no call to an OpenClaw spawning command, no session/sub-agent creation, no coordinator logic, no task decomposition, and no result collection or aggregation in the code shown. Additionally, the script writes to the user's home-directory workspace log path, while declared permissions are empty. That filesystem access is modest, but it is still an undeclared resource interaction. Therefore the declared description materially overstates what the code actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The description claims a multi-agent parallel work system built on OpenClaw sessions_spawn with coordinator mode, task assignment, and summary capabilities. The code instead is a lightweight team bookkeeping script that writes JSON state under ~/.openclaw/workspace/memory/activity/multi-agent. The 'spawn' action does not start any real agent/session/process; it just creates a worker.json file and appends metadata to team.json. There is no coordinator logic, no actual inter-agent communication, no OpenClaw API or sessions_spawn usage, and no true parallel execution control. While the script is related to team/worker management and task tracking, its primary behavior is administrative state management rather than implementing the declared multi-agent execution system. Therefore the description materially overstates the actual functionality.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

worker_id is used directly in rm -rf "$TEAM_DIR/workers/$worker_id" with no validation or canonicalization. An attacker who can supply values like ../... can trigger path traversal and delete arbitrary directories accessible to the current user, making this much more dangerous in an agent skill that may consume external task parameters.

Content

Scanner excerpt · scripts/team.sh (reported line 224)May include surrounding context.

sh
return 1
    fi
    
    rm -rf "$TEAM_DIR/workers/$worker_id"
    
    # 从团队成员中移除
    python3 << PYEOF

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The cleanup function deletes the entire workers directory with rm -rf and recreates it, which wipes all worker records. While it logs that cleanup is occurring, it does not explicitly disclose that all worker data will be permanently deleted or ask for confirmation.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/team.sh (reported line 266)May include surrounding context.

sh
done
    
    # 清理目录
    rm -rf "$TEAM_DIR/workers"
    mkdir -p "$TEAM_DIR/workers"
    
    echo "✅ 清理完成"

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The skill name, description, aliases, and operational instructions are entirely presented in Chinese, with no indication that users may choose another language or that the skill is intended only for a Chinese-language environment. Under the stated policy, a language constraint should be optional or clearly justified.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger phrases are broad enough that ordinary user requests about parallel help or multi-agent discussion may activate this skill unintentionally. In a skill that can influence orchestration behavior and potentially enable subagent spawning, overbroad activation increases the chance of unexpected tool use, resource consumption, and user confusion.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Using a common everyday phrase like '帮我同时处理...' as an activation condition can cause accidental triggering during normal conversation. In context, this is more dangerous because the skill is designed around coordinating parallel workers, so unintended activation could lead to unnecessary subagent creation, extra cost, or unintended task decomposition.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

文档前文在 L081-L091、L101-L123 明确说明 sessions_spawn 立刻返回、完成结果通过 announce push 回来,并要求用 sessions_yield 等待后续结果。但 L192-L200 的示例却把它放进 await/try...catch 中,暗示调用方可直接等待任务完成并以该方式处理失败,这与文档自身描述的执行语义相冲突。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

This shell script's natural-language comments, usage instructions, and user-visible status messages are written exclusively in Chinese, and there is no indication that users can choose another language or that the skill is intentionally restricted to a Chinese-speaking context. That creates a locale/language policy issue under the requirement to avoid forcing a specific language without opt-in.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script writes the raw user-supplied task string into a persistent markdown log under the user's home directory without any notice, consent, redaction, or retention control. In a multi-agent workflow, task text can easily contain sensitive prompts, code, credentials, internal project details, or personal data, so persistent storage increases the chance of later disclosure through local access, backups, syncing, or accidental sharing.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script's user-facing comments, usage text, and runtime messages are entirely in Chinese, which imposes a specific language for interaction. There is no indication that users may select another language or that the locale restriction is intentional and documented.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file defines leave_team() and the header/help text advertise ./team.sh leave <worker-id> as supported functionality. However, in the command dispatcher the leave case invokes leave_worker, which is not defined, so the documented behavior is contradicted by the actual code path and the leave operation will not work as described.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The leave operation performs rm -rf on the worker directory, which deletes stored worker state. Although the script prints usage help elsewhere, there is no confirmation prompt or explicit warning at the point of deletion that user data for that worker will be removed.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

This shell script presents the suggested user invocation and agent commands only in Chinese, implying a fixed language for interaction. The file does not offer an opt-in language choice or explain that the skill is intentionally limited to a Chinese-speaking context, which can violate language/locale policy requirements.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

Comments, usage examples, and runtime output are presented in Chinese, and the script does not provide any option to select another language. This can violate a language/locale policy when a skill forces a specific language without user opt-in.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.