Back to skill

Security audit

多 Agent 团队协作

Security checks for vulnerabilities and agentic risk

Overview

This skill is a real OpenClaw team deployment helper, but its deployment script handles credentials and user-provided paths/code unsafely enough that it should be reviewed before installation.

Install only after reviewing or fixing scripts/deploy.sh. In particular, do not run it as root or against production OpenClaw credentials until identifiers are strictly validated, generated Python is data-driven rather than source-interpolated, path containment is enforced, and child agents receive scoped credentials instead of copies of the main auth profile.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/deploy.sh:107
Finding
Arbitrary Command Execution Through Unvalidated Bash Array Subscripts<![CDATA[ ## Vulnerability Details **File Location**: `scripts/deploy.sh`, lines 107-119 **Vulnerability Type**: Bash arithmetic array-subscript injection **Risk Level**: Critical ### Vulnerable Code ```bash TEAMS="" TEAM_MEMBERS="" read -p "要创建几个团队?[1-10]: " team_count if ! [[ "$team_count" =~ ^[0-9]+$ ]] || [ "$team_count" -lt 1 ] || [ "$team_count" -gt 10 ]; then log_error "团队数量必须在 1-10 之间" exit 1 fi for ((i=1; i<=team_count; i++)); do echo "" log_step "配置第 $i 个团队" read -p "团队 ID (英文,如 code/stock): " team_id read -p "团队名称 (中文,如 代码开发团队): " team_name read -p "团队领导角色 (如 CTO/CIO): " team_role read -p "团队成员 (逗号分隔,如 frontend,backend,test): " members TEAMS="$TEAMS $team_id" TEAM_MEMBERS["$team_id"]="$members" ``` ### Technical Analysis `TEAM_MEMBERS` is initialized as a scalar value instead of being declared as an associative array. Consequently, Bash treats the later `TEAM_MEMBERS["$team_id"]` operation as an indexed-array assignment. Indexed-array subscripts are evaluated as Bash arithmetic expressions. Arithmetic evaluation can perform additional expansion of attacker-controlled content. Because `team_id` is read directly from interactive input without validation, a malicious array subscript can cause command substitution or other unintended shell evaluation during the assignment. The documentation specifies an identifier format but the script does not enforce it. Quoting `"$team_id"` inside the array syntax does not convert an indexed array into an associative array and does not eliminate arithmetic evaluation. ### Attack Path 1. An attacker or untrusted operator starts `scripts/deploy.sh`. 2. The attacker selects custom-team configuration. 3. The attacker enters a syntactically valid team count. 4. For the team ID, the attacker supplies an arithmetic-array expression containing shell expansion or command substitution. 5. Bash evaluates the untrusted subscript while executing: `TEAM_MEMBERS["$team_id"]="$ ...[truncated 687 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Declare the collection as an associative array before any assignment: ```bash declare -A TEAM_MEMBERS=() ``` 2. Enforce a strict identifier allowlist: ```bash if [[ ! "$team_id" =~ ^[a-z][a-z0-9_-]{0,63}$ ]]; then log_error "Invalid team ID" exit 1 fi ``` 3. Read input without processing backslash escapes: ```bash read -r -p "Team ID: " team_id ``` 4. Apply equivalent validation to every member identifier. 5. Do not rely on documentation as an input-control mechanism. 6. Run the deployment script under a dedicated, minimally privileged account rather than root. 7. Add automated tests for command substitutions, arithmetic expressions, quotes, whitespace, and metacharacters in identifiers. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/deploy.sh:232
Finding
Arbitrary Python Code Injection Through an Unquoted Generated Heredoc<![CDATA[ ## Vulnerability Details **File Location**: `scripts/deploy.sh`, lines 232-247 **Vulnerability Type**: Python source-code injection **Risk Level**: Critical ### Vulnerable Code ```bash python3 << EOF import json teams = "$TEAMS".split() team_members = {} # 预设成员 presets = { "code": ["frontend", "backend", "test", "product", "algorithm", "audit"], "stock": ["analysis", "risk", "portfolio", "research"], "social": ["content", "scheduling", "engagement", "analytics"], "flow": ["workflow", "cron", "integration", "monitor"] } # 读取团队成员 team_members_raw = """$(declare -p TEAM_MEMBERS 2>/dev/null || echo "")""" ``` ### Technical Analysis The heredoc delimiter is unquoted, so Bash performs parameter expansion and command substitution on its body before passing it to Python. The attacker-controlled `TEAMS` value is inserted directly into executable Python source: ```python teams = "$TEAMS".split() ``` A team ID containing quotes and Python syntax can terminate the intended string literal and inject additional Python statements. The generated content is then immediately interpreted by `python3`. The script also embeds the result of `declare -p TEAM_MEMBERS` in a Python triple-quoted string. This mixes shell-generated representations with executable source and creates an additional fragile parsing boundary. The underlying issue is treating untrusted data as program source instead of passing it through a structured data channel. ### Attack Path 1. An attacker starts the deployment script and selects a mode that accepts custom team identifiers. 2. The attacker enters a team ID containing Python string-termination syntax and an additional Python statement. 3. The value is appended to `TEAMS` without validation or encoding. 4. `generate_config_snippet` expands `TEAMS` into the unquoted heredoc. 5. Python parses the attacker's content as executable code rather than as a team name. 6. The injected Python statement executes with the deploymen ...[truncated 627 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not interpolate input into Python source. 2. Pass validated values as JSON data, environment variables, standard input, or command-line arguments. 3. Quote the heredoc delimiter so Bash cannot expand its contents: ```bash python3 > "$OUTPUT_FILE" <<'PYTHON' import json import os teams = json.loads(os.environ["OPENCLAW_TEAMS_JSON"]) PYTHON ``` 4. Construct the environment value with a trusted JSON serializer rather than manual quoting. 5. Validate every team and member identifier before serialization. 6. Remove the `declare -p` embedding. It is a shell-language representation, not a safe interchange format. 7. Keep user-controlled values exclusively in data structures and never evaluate them with `exec`, `eval`, or generated source. 8. Add regression tests using quotes, triple quotes, newlines, backslashes, semicolons, and Python syntax. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/deploy.sh:113
Finding
Directory Traversal Through Unvalidated Team and Member Identifiers<![CDATA[ ## Vulnerability Details **File Location**: `scripts/deploy.sh`, lines 113-183 **Vulnerability Type**: Path traversal and unauthorized filesystem modification **Risk Level**: High ### Vulnerable Code ```bash read -p "团队 ID (英文,如 code/stock): " team_id read -p "团队名称 (中文,如 代码开发团队): " team_name read -p "团队领导角色 (如 CTO/CIO): " team_role read -p "团队成员 (逗号分隔,如 frontend,backend,test): " members TEAMS="$TEAMS $team_id" TEAM_MEMBERS["$team_id"]="$members" ``` ```bash for team in $TEAMS; do log_step "创建 $team 团队目录..." # 团队领导目录 mkdir -p "$OPENCLAW_DIR/agents/teams/$team"/{workspace,agent,sessions} # 获取成员列表 if [ -n "${TEAM_MEMBERS[$team]}" ]; then members="${TEAM_MEMBERS[$team]}" else members="${TEAM_TEMPLATES[$team]}" fi # 创建成员目录 IFS=',' read -ra MEMBER_ARRAY <<< "$members" for member in "${MEMBER_ARRAY[@]}"; do member=$(echo "$member" | xargs) if [ -n "$member" ]; then mkdir -p "$OPENCLAW_DIR/agents/teams/$team/$member"/{workspace,agent,sessions} log_info " 创建成员:$member" fi done done ``` ### Technical Analysis The script uses attacker-controlled team and member identifiers as path components without validating them. Values containing `../` are normalized by the operating system during `mkdir` and subsequent file operations, permitting paths to escape `/root/.openclaw/agents/teams`. Shell quoting prevents word splitting and wildcard expansion, but it does not prevent directory traversal. The documented lowercase naming convention is not enforced by the implementation. Member values are trimmed with `xargs`, but trimming whitespace does not make them safe filesystem components. ### Attack Path 1. An attacker selects custom-team mode. 2. The attacker supplies a team ID or member identifier containing one or more `../` path components. 3. The value is stored without validation. 4. `create_directories` concatenates the value with `/root/.opencla ...[truncated 979 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Enforce strict allowlists for team and member identifiers: ```bash validate_id() { [[ "$1" =~ ^[a-z][a-z0-9_-]{0,63}$ ]] } ``` 2. Reject empty identifiers, dots, slashes, control characters, whitespace, and identifiers beginning with a hyphen. 3. Resolve each proposed destination and verify containment before writing: ```bash base="$(realpath -m "$OPENCLAW_DIR/agents/teams")" target="$(realpath -m "$base/$team")" case "$target" in "$base"/*) ;; *) log_error "Path escapes team directory"; exit 1 ;; esac ``` 4. Perform the containment check again for every member path. 5. Use `mkdir -- "$target/workspace" "$target/agent" "$target/sessions"` after validation. 6. Refuse to follow unexpected symbolic links in destination paths. 7. Run deployment with only the filesystem privileges required to manage the intended OpenClaw directory. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/deploy.sh:193
Finding
Main-Agent Authentication Profiles Are Replicated to Every Generated Agent<![CDATA[ ## Vulnerability Details **File Location**: `scripts/deploy.sh`, lines 193-220 **Vulnerability Type**: Excessive credential distribution and privilege-boundary violation **Risk Level**: High ### Vulnerable Code ```bash copy_auth_configs() { log_info "复制认证配置文件..." for team in $TEAMS; do # 团队领导 cp "$OPENCLAW_DIR/agents/main/agent/auth-profiles.json" \ "$OPENCLAW_DIR/agents/teams/$team/agent/" 2>/dev/null || true cp "$OPENCLAW_DIR/agents/main/agent/models.json" \ "$OPENCLAW_DIR/agents/teams/$team/agent/" 2>/dev/null || true # 获取成员列表并复制 if [ -n "${TEAM_MEMBERS[$team]}" ]; then members="${TEAM_MEMBERS[$team]}" else members="${TEAM_TEMPLATES[$team]}" fi IFS=',' read -ra MEMBER_ARRAY <<< "$members" for member in "${MEMBER_ARRAY[@]}"; do member=$(echo "$member" | xargs) if [ -n "$member" ]; then cp "$OPENCLAW_DIR/agents/main/agent/auth-profiles.json" \ "$OPENCLAW_DIR/agents/teams/$team/$member/agent/" 2>/dev/null || true cp "$OPENCLAW_DIR/agents/main/agent/models.json" \ "$OPENCLAW_DIR/agents/teams/$team/$member/agent/" 2>/dev/null || true fi done done log_info "认证配置复制完成" } ``` ### Technical Analysis The script copies the main agent's complete `auth-profiles.json` into every generated team leader and member directory. This violates least privilege because all generated agents receive the main agent's credential material rather than narrowly scoped, agent-specific credentials. The number of credential copies grows with every generated agent. Compromise of any one destination can therefore expose credentials originating from the main agent. The operation also interacts dangerously with the path-traversal vulnerability: a crafted destination can cause credential files to be copied outside the intended hierar ...[truncated 1439 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not copy the main agent's complete authentication profile to child agents. 2. Provision unique, narrowly scoped credentials for each team or agent. 3. Separate non-secret model configuration from authentication material. 4. Copy only explicitly required fields after applying a documented allowlist. 5. Set restrictive ownership and permissions on every credential file: ```bash install -m 0600 -o appropriate_user -g appropriate_group source destination ``` 6. Ensure generated agents cannot read one another's credential directories. 7. Replace `2>/dev/null || true` with explicit error handling and rollback for credential operations. 8. Maintain a credential inventory and support revocation for each generated agent. 9. Warn the operator before any sensitive credential propagation and require explicit confirmation. 10. Combine this remediation with strict path validation and symbolic-link defenses. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • 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
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The skill advertises interactive deployment, presets, custom team creation, and hybrid mode, but the analyzed behavior reportedly only reads local configuration and invokes `openclaw` CLI checks for audit/verification. This mismatch can mislead users into granting trust or running commands under false assumptions, which is a security-relevant integrity issue because operators may execute a skill believing it performs safe deployment logic when it actually inspects local state and performs validation actions.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The skill documentation is entirely in Chinese and the interactive examples explicitly require Chinese input such as '团队名称 (中文,如 代码开发团队)'. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is clearly documented and justified, which is not present here.

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The manifest description forces a specific language/locale presentation for users by providing the core skill summary only in Chinese. The file does not indicate that the skill is region-specific or that users may choose another language, which conflicts with the language/locale policy criteria.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The operational instructions, usage guidance, and warnings are all written in Chinese, effectively imposing a language requirement on users. There is no opt-in, alternative language, or documented reason that the skill must be Chinese-only.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The manifest and script banner emphasize support for 自定义团队结构, and earlier code collects custom team/member input. However, the Python generator does not parse or use TEAM_MEMBERS; it explicitly comments '简化处理,使用预设' and builds agent lists from hardcoded presets or ['member1', 'member2'], so the actual deployed config snippet does not reflect the user's custom structure.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The --preset path immediately backs up configuration, creates directories under /root/.openclaw, and copies authentication-related files without prompting the user or printing a clear warning before making those changes. Although the interactive path has a confirmation for preset selection, that disclosure does not apply when the script is run directly with --preset.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The script's comments and all user-visible status messages are in Chinese, including the banner and validation results. This imposes a specific language on users without opt-in or documented locale justification, which matches the language/locale policy violation category.

Natural-Language Policy Violations

Low
Confidence
92% confidence
Finding
The package description is written only in Chinese ("交互式部署多 Agent 团队协作架构,支持自定义团队结构") with no indication that users can choose another language or that the skill is intended exclusively for a Chinese-language audience. This creates a natural-language locale constraint in metadata that may violate language-choice policy for general-purpose skills.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
Comments and all interactive prompts are written in Chinese, and the script does not provide any option to select another language or indicate that it is intended only for a Chinese-speaking environment. This creates a natural-language locale constraint without user opt-in.

Intent-Code Divergence

Low
Confidence
91% confidence
Finding
The comment '# 读取团队成员' suggests the generator will consume the collected team member configuration. In practice, the next line notes '简化处理,使用预设', and the loop uses presets.get(...) rather than parsed TEAM_MEMBERS, which contradicts the stated intent of that section.

Static analysis

No suspicious patterns detected.