Back to skill

Security audit

Coding Team Setup

Security checks for vulnerabilities and agentic risk

Overview

This is a real OpenClaw team setup wizard, but it includes under-scoped persistent telemetry/cron instructions and unsafe setup code that can overwrite or remove unintended OpenClaw files or agent configuration.

Review before installing. Use this only in an OpenClaw environment where you are comfortable letting the wizard modify global agent configuration and create persistent agent files. Avoid untrusted team names or custom role IDs, keep backups, inspect diffs before restarting the gateway, and do not enable the weekly telemetry/optimization cron unless you add explicit opt-in, redaction, retention, and review controls.

Vulnerability Patterns
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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)

T06 · System Persistence

Error
Location
SKILL.md:197
Finding
Mandatory Cross-Session Cron Task Performs Autonomous Global Configuration and Memory Writes<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:197-218` **Vulnerability Type**: Persistent scheduled task with autonomous state modification **Risk Level**: High ### Vulnerable Code Snippet ```markdown ### Standard Post-Setup Workflow (UPDATED in v2.2) After creating any sub-agent team, execute this as **mandatory standard flow**: 1. **Core skill baseline assignment** - Assign 2–4 core skills per role directly in `openclaw.json` - Keep advanced/domain skills as on-demand skills 2. **Skill learning telemetry** - Enable usage logging per agent/skill - Log format: `agent_id + skill_name + timestamp + context` 3. **Weekly optimization task (OpenClaw Cron)** - Create a weekly `openclaw cron` job in isolated session - Analyze last 7 days usage and update `openclaw.json` skill mapping - Always backup before writing config 4. **All-team scope** - Mechanism must apply to **all teams** (coding/wealth/other future teams) - No team-specific hardcoding in the optimizer 5. **Review outputs** - Save weekly optimization summary to `memory/YYYY-MM-DD.md` - Keep optimization history under `.lib/skill_analytics/` ``` ### Technical Analysis The Skill directs the agent or operator to install a recurring OpenClaw cron task as a mandatory post-setup action. That task is expected to collect agent and skill usage context, analyze activity, modify `openclaw.json`, and write results to persistent memory and analytics directories. This workflow survives the original Skill invocation and applies to all current and future teams rather than only the team being configured. The documentation does not define an implementation with strict input validation, an allowlist of permissible configuration changes, retention limits, redaction of logged context, or a mandatory human-approval gate before writing the updated configuration. Although the supplied `wizard/setup.js` does not itself create the cron task, the instruction is explicitly ...[truncated 1508 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the requirement that cron installation is mandatory. 2. Make telemetry and scheduled optimization separate, explicit opt-in features. 3. Present the exact cron command, schedule, executable, input files, and output files before installation. 4. Scope optimization to the selected team by default instead of all teams. 5. Require human review and approval of a generated configuration diff before modifying `openclaw.json`. 6. Restrict updates to an allowlisted set of configuration fields. 7. Redact secrets, credentials, source code, personal information, and user content from telemetry context. 8. Define retention limits and provide commands to inspect, disable, and remove the cron task and stored analytics. 9. Run the optimizer under a least-privileged identity with access only to required files. 10. Use atomic writes, schema validation, backups, rollback on failure, and integrity checks for every configuration update. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
wizard/setup.js:190
Finding
Path Traversal Through Unvalidated Team Names and Custom Role IDs<![CDATA[ ## Vulnerability Details **File Locations**: `wizard/setup.js:190-197`, `wizard/setup.js:232-263`, `wizard/setup.js:499-513`, `wizard/setup.js:534-537` **Vulnerability Type**: Path traversal and arbitrary file overwrite **Risk Level**: High ### Vulnerable Code Snippets Team names are accepted from a command-line argument or interactive input without validation: ```javascript // ── Step 2: Team name ── step(2, 'Team configuration'); const teamName = argTeam || await askDefault('Team name (用于区分多个团队)', 'default'); const teamPrefix = teamName === 'default' ? '' : `${teamName}-`; ok(`Team: ${teamName}`); ``` Custom role IDs are also accepted without validation: ```javascript while (adding && Object.keys(selectedRoles).length < 10) { const cId = await ask(' Role ID (lowercase, e.g. "ml-engineer"): '); if (!cId) { adding = false; break; } const cName = await askDefault(' Display name', cId); const cEmoji= await askDefault(' Emoji', '🔧'); const cDesc = await askDefault(' Description', `${cName} — custom role`); const cVibe = await askDefault(' Vibe', 'Professional'); const cResp = await ask(' Responsibilities (comma-separated): '); const modelTypeIdx = await choose(' Default model type', [ 'Strongest Reasoning', 'Code Specialized', 'Balanced', 'Fast', 'Long Context' ]); const modelTypes = ['strongest', 'code', 'balanced', 'fast', 'longContext']; selectedRoles[cId] = { id: cId, name: cName, emoji: cEmoji, category: 'custom', description: cDesc, defaultModel: modelTypes[modelTypeIdx], vibe: cVibe, responsibilities: cResp ? cResp.split(',').map(s => s.trim()) : [] }; ``` The untrusted values are then used to construct filesystem paths: ```javascript for (const [roleId, role] of Object.entries(selectedRoles)) { const agentId = `${teamPrefix}${roleId}`; const wsPath = path.join(openclawPath, 'agents', agentId, 'workspace'); if (!fs.existsSync(wsPath)) { fs.mkdirSync(wsPath, { ...[truncated 3233 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate team names and role IDs before using them. A suitable baseline is: ```javascript const SAFE_ID = /^[a-z0-9][a-z0-9_-]{0,63}$/; ``` 2. Reject absolute paths, path separators, traversal components, control characters, empty identifiers, and reserved object-property names. 3. Resolve each destination and verify containment before any filesystem operation: ```javascript function safeChild(base, ...parts) { const resolvedBase = path.resolve(base) + path.sep; const target = path.resolve(base, ...parts); if (!target.startsWith(resolvedBase)) { throw new Error('Path escapes the permitted directory'); } return target; } ``` 4. Apply containment checks separately to agent workspaces and team manifests. 5. Use `fs.realpathSync()` or equivalent checks on existing parent directories to defend against symbolic-link escapes. 6. Refuse to overwrite existing instruction files by default. Require explicit confirmation or use exclusive creation flags where appropriate. 7. Store a normalized internal identifier separately from the user-facing display name. 8. Validate identifiers before creating the backup or making any configuration changes. 9. Add tests for `../`, repeated traversal, absolute paths, Windows separators, Unicode separator variants, control characters, and symlink-based escape attempts. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
wizard/setup.js:441
Finding
Regex Injection and Destructive Removal of Unrelated Agent Configurations<![CDATA[ ## Vulnerability Details **File Location**: `wizard/setup.js:441-450` and `wizard/setup.js:477-490` **Vulnerability Type**: Regex injection and unsafe destructive configuration update **Risk Level**: High ### Vulnerable Code Snippets The user-controlled team prefix is interpolated directly into a regular expression: ```javascript // Remove old team agents (matching prefix) but keep main + other teams const prefixPattern = teamPrefix ? new RegExp(`^${teamPrefix}`) : null; config.agents.list = config.agents.list.filter(a => { if (a.default === true) return true; // If we have a prefix, only remove agents with that prefix if (prefixPattern) return !prefixPattern.test(a.id); // If default team, remove agents whose id matches any selected role OR old non-prefixed agents return false; // remove all non-main for default team }); ``` The same injected expression is used while rebuilding the main agent allowlist: ```javascript // Update main agent allowAgents const mainIdx = config.agents.list.findIndex(a => a.default === true); if (mainIdx === -1) { config.agents.list.unshift({ id: 'main', default: true, name: 'Main Agent', workspace, subagents: { allowAgents: newAgentIds }, }); } else { if (!config.agents.list[mainIdx].subagents) { config.agents.list[mainIdx].subagents = {}; } // Merge with existing allowAgents (other teams' agents) const existing = config.agents.list[mainIdx].subagents.allowAgents || []; const merged = [...new Set([...existing.filter(id => { // Keep agents from other teams if (prefixPattern) return !prefixPattern.test(id); return false; }), ...newAgentIds])]; config.agents.list[mainIdx].subagents.allowAgents = merged; } ``` ### Technical Analysis `teamName` is user-controlled, and `teamPrefix` is derived from it without escaping regular-expression metacharacters. Constructing `new RegExp(\`^${teamPrefix}\`)` therefore allows the team name to alter the expression's meaning. For ...[truncated 2644 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not use a regular expression for literal prefix matching. Use normalized identifiers and `startsWith()`: ```javascript const belongsToTeam = id => id.startsWith(teamPrefix); ``` 2. If a regular expression is unavoidable, strictly validate the identifier and escape every regex metacharacter before constructing it. 3. Add an explicit immutable `team` property to each generated agent entry and remove agents by exact ownership: ```javascript config.agents.list = config.agents.list.filter( agent => agent.default === true || agent.team !== teamName ); ``` 4. For the default team, remove only agents recorded in the previous default-team manifest. Never interpret “default” as ownership of every non-default agent. 5. Compute and display a configuration diff before writing, including every agent and allowlist entry scheduled for removal. 6. Require explicit confirmation if the operation would remove agents not present in the selected team's existing manifest. 7. Abort if the number of removed agents exceeds the expected number for the selected team. 8. Write configuration atomically to a temporary file, validate its schema and invariants, then rename it into place. 9. Automatically restore the backup if validation or writing fails. 10. Add regression tests covering team names with `.`, `*`, `+`, `?`, `|`, parentheses, brackets, anchors, and backslashes, as well as coexistence between default and named teams. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (11)

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The README advertises automatic modification of `openclaw.json`, workspaces, manifests, and setup of a recurring optimization cron, but it does not clearly warn users that running the wizard changes local files and may install persistent scheduled behavior. In an agent skill context, undisclosed state changes and persistence increase the chance of unsafe execution, accidental configuration drift, or abuse by a downstream script that performs broader modifications than the documentation suggests.

Natural-Language Policy Violations

Medium
Confidence
84% confidence
Finding
The document is explicitly structured around English and Chinese sections and the activation examples include language-specific commands, but it does not state that users may choose their preferred language or that the skill is limited to a specific locale for compliance reasons. Under the policy, forcing a specific language without opt-in can be a locale policy violation.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill explicitly requires per-agent skill usage telemetry including `agent_id + skill_name + timestamp + context` without any notice, consent mechanism, minimization guidance, or restriction on what may appear in `context`. Because this applies across agents and workflows, it can silently collect sensitive user or project data and normalize privacy-invasive monitoring.

Ssd 3

Medium
Confidence
97% confidence
Finding
Taken together, the telemetry and archival requirements create a broad data collection and retention pipeline across all teams, explicitly logging usage context and preserving optimization artifacts. In a multi-agent development environment, that context may contain credentials, proprietary code, incident details, or personal data, making the skill materially more dangerous than a generic logging suggestion.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill mandates saving weekly optimization summaries to `memory/YYYY-MM-DD.md` and keeping optimization history under `.lib/skill_analytics/` with no retention or sensitivity controls. Persistent archival of operational summaries can accumulate sensitive prompts, project details, and behavioral metadata over time, increasing exposure in the event of local compromise or overbroad access.

Ssd 3

Medium
Confidence
96% confidence
Finding
The Chinese section repeats the same mandatory cross-team tracking, optimization, and archival instructions, confirming this is not an incidental translation artifact but a deliberate feature of the skill. The bilingual duplication broadens the chance of deployment and reinforces persistent storage of potentially sensitive usage context across current and future teams.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The file contains English metadata and model labels alongside Chinese descriptions and responsibilities, effectively imposing mixed locale output without any opt-in or documented language selection. This can violate language/locale policy when users are not given a choice of interface or content language.

Vague Triggers

Medium
Confidence
83% confidence
Finding
This is a manifest JSON file, so vague-trigger checks apply. The note says users can define "fully custom roles via the wizard" but gives no constraints, trigger scope, or exclusion conditions for what qualifies as an acceptable custom role, which makes invocation/activation boundaries ambiguous.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The collaboration and notes sections contain instructions written only in Chinese, which imposes a specific language on downstream skill authors and users without offering a language choice or documenting a justified locale constraint. This matches the policy category for language or locale restrictions in natural-language content.

Scope Creep

Low
Category
Excessive Agency
Content
- Set up a multi-role collaborative development team (2–10 agents)
- Need multiple teams to work in parallel with independent configurations
- Need custom collaboration workflows (not limited to standard 9-step)
- Need flexible role combinations and model assignments

### Quick Start
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
The user-facing prompt `Team name (用于区分多个团队)` embeds Chinese text in the interactive flow, which imposes a specific language/locale in at least part of the skill experience. There is no surrounding language selection or opt-in mechanism to let users choose their preferred locale.