Back to skill

Security audit

Dev Team

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent multi-agent development orchestrator, but it defaults to powerful agent and local automation paths that can modify code, run shell commands, post to GitHub, persist scheduled jobs, and act without enough containment.

Install only if you are comfortable giving this skill broad local developer authority. Before use, remove dangerous approval-bypass defaults, avoid running it on untrusted repositories, disable automatic package installs or use --ignore-scripts in a sandbox, bind the dashboard to loopback with authentication, keep ENABLE_LOCAL_ACTIONS off unless needed, and do not register cron or LaunchAgent jobs until you have a removal plan and trust the script directory.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
Findings (5)

T06 · System Persistence

Warning
Location
references/initialization.md:15
Finding
Persistent Scheduled Execution Through Cron and LaunchAgents<![CDATA[ ## Vulnerability Details **File Location**: `references/initialization.md:15-52, 63-70, 74-96` **Vulnerability Type**: Scheduled cross-session execution **Risk Level**: Medium ### Vulnerable Code ```bash # Monitor agent status every 10 minutes openclaw cron add \ --name dev-team-monitor \ --cron "*/10 * * * *" \ --command scripts/check-agents.sh \ --working-dir /Users/Vint/.openclaw/workspace/skills/dev-team \ --session isolated \ --no-deliver \ --message "Run the dev-team monitoring script" # Clean worktrees daily openclaw cron add \ --name dev-team-cleanup \ --cron "0 3 * * *" \ --command scripts/cleanup-worktrees.sh \ --working-dir /Users/Vint/.openclaw/workspace/skills/dev-team \ --session isolated \ --no-deliver ``` ```bash crontab -e */10 * * * * cd /path/to/skills/dev-team && ./scripts/check-agents.sh >> ./assets/logs/cron.log 2>&1 0 3 * * * cd /path/to/skills/dev-team && ./scripts/cleanup-worktrees.sh >> ./assets/logs/cleanup.log 2>&1 10 3 * * * cd /path/to/skills/dev-team && ./scripts/prune-history.sh --keep-days 7 --keep-count 50 >> ./assets/logs/prune.log 2>&1 ``` ```xml <plist version="1.0"> <dict> <key>Label</key> <string>com.dev-team.agent-check</string> <key>ProgramArguments</key> <array> <string>/bin/bash</string> <string>/path/to/skills/dev-team/scripts/check-agents.sh</string> </array> <key>StartInterval</key> <integer>600</integer> </dict> </plist> ``` ```bash launchctl load ~/Library/LaunchAgents/com.dev-team.agent-check.plist ``` ### Technical Analysis The initialization guide instructs users to establish recurring execution through OpenClaw cron, the operating-system crontab, or a macOS LaunchAgent. These mechanisms survive the original Skill session and repeatedly execute scripts with the permissions of the account that registered them. Periodic monitoring and cleanup are relevant to multi-agent orchestration, so the mechanism has a legitimate operati ...[truncated 1318 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Make all persistence mechanisms explicitly optional rather than presenting them as required initialization. - Prefer foreground monitoring or a manually started supervisor for ordinary use. - Document complete removal procedures, including: - `openclaw cron remove <job>` - removal of the relevant crontab entries - `launchctl unload <plist>` followed by deletion of the plist - Run scheduled tasks in a dedicated, least-privileged account or isolated execution environment. - Use absolute, administrator-approved paths and reject writable or symlinked script locations. - Verify script ownership, permissions, and integrity before every scheduled execution. - Restrict inherited environment variables and credential access. - Log registration, execution, updates, and removal of persistent jobs. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
config/agents.json:3
Finding
Default Agent Configuration Disables Approval and Sandbox Protections<![CDATA[ ## Vulnerability Details **File Location**: `config/agents.json:3-27`; `scripts/spawn-agent.sh:477-506`; `scripts/review-agent.sh:334-351` **Vulnerability Type**: Excessive agent permissions and unsafe tool configuration **Risk Level**: Critical ### Vulnerable Code ```json { "agents": { "codex": { "command": "codex", "args": ["exec", "--dangerously-bypass-approvals-and-sandbox"], "cwdArg": "-C", "modelArg": "--model" }, "claude": { "command": "claude", "args": ["--dangerously-skip-permissions", "-p"], "cwdArg": null, "modelArg": "--model" }, "gemini": { "command": "gemini", "args": [ "--approval-mode", "yolo", "--allowed-tools", "run_shell_command,write_file,read_file,grep_search", "-p" ] } } } ``` The hardcoded fallback in `scripts/spawn-agent.sh` preserves the same unsafe behavior: ```bash case $agent_type in codex) if [[ -n "$agent_model" ]]; then echo "codex exec --dangerously-bypass-approvals-and-sandbox -C '$worktree' --model '$agent_model' '$prompt'" else echo "codex exec --dangerously-bypass-approvals-and-sandbox -C '$worktree' '$prompt'" fi ;; claude) if [[ -n "$agent_model" ]]; then echo "claude --dangerously-skip-permissions -p --model '$agent_model' '$prompt'" else echo "claude --dangerously-skip-permissions -p '$prompt'" fi ;; gemini) echo "gemini -p '$prompt'" ;; esac ``` Review agents are also run with protections disabled: ```bash _run_review_cmd "$output_file" "$REPO_PATH" \ codex exec --dangerously-bypass-approvals-and-sandbox "$prompt" _run_review_cmd "$output_file" "$REPO_PATH" \ claude --dangerously-skip-permissions -p "$prompt" ``` ### Technical Analysis The default agent configuration deliberately disables command approval and sandbox restrictions. Gemini is p ...[truncated 1873 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove `--dangerously-bypass-approvals-and-sandbox`, `--dangerously-skip-permissions`, and YOLO approval mode from all defaults. - Require an explicit, per-invocation opt-in before any dangerous execution mode is enabled. - Run build agents inside disposable containers or operating-system sandboxes. - Mount only the assigned worktree as writable. - Keep home directories, SSH material, cloud credentials, GitHub credentials, and unrelated repositories outside the sandbox. - Disable network access unless the task explicitly requires it. - Create separate profiles: - Build: worktree-scoped write and test permissions. - Review: read-only repository access with no shell or write tools. - Planning: no write, shell, or network capabilities. - Require user approval for destructive Git commands, dependency installation, network publication, and access outside the worktree. - Pass a minimal environment instead of inheriting all user environment variables. - Record every privileged tool invocation in an immutable audit log. ]]>

T01 · Skill Instruction Hijacking

Error
Location
scripts/review-agent.sh:230
Finding
PR Diff Prompt Injection Reaches Privileged Review Agents<![CDATA[ ## Vulnerability Details **File Location**: `scripts/review-agent.sh:230-303, 334-351` **Vulnerability Type**: Indirect prompt injection through attacker-controlled PR content **Risk Level**: High ### Vulnerable Code ```bash if gh pr diff "$PR_NUM" --repo "$REPO" > "$PR_DIFF_FILE" 2>/dev/null; then python3 - <<PYEOF from pathlib import Path p = Path("$PR_DIFF_FILE") text = p.read_text(encoding="utf-8", errors="replace") max_chars = 12000 max_lines = 220 lines = text.splitlines() excerpt = "\n".join(lines[:max_lines]) if len(excerpt) > max_chars: excerpt = excerpt[:max_chars] if len(lines) > max_lines or len(text) > len(excerpt): excerpt += "\n\n[... diff truncated by dev-team review-agent ...]\n" Path("$PR_DIFF_EXCERPT_FILE").write_text(excerpt, encoding="utf-8") PYEOF fi ``` ```bash diff_context="$(cat "$PR_DIFF_EXCERPT_FILE" 2>/dev/null || echo 'Diff unavailable')" prompt=$(printf '%s\n' \ "You are a dev-team PR review subagent." \ "REVIEWER_NAME: $reviewer" \ "PR_NUMBER: $PR_NUM" \ "PR_URL: $PR_URL" \ "REPO: $REPO" \ "BASE_REF: $BASE_REF" \ "HEAD_REF: $HEAD_REF" \ "" \ "Review the PR metadata and diff excerpt below." \ "" \ "=== DIFF_EXCERPT_BEGIN ===" \ "$diff_context" \ "=== DIFF_EXCERPT_END ===") ``` ```bash case "$reviewer" in codex) _run_review_cmd "$output_file" "$REPO_PATH" \ codex exec --dangerously-bypass-approvals-and-sandbox "$prompt" ;; claude) _run_review_cmd "$output_file" "$REPO_PATH" \ claude --dangerously-skip-permissions -p "$prompt" ;; esac ``` ### Technical Analysis A pull-request diff is attacker-controlled content. The script inserts the diff excerpt verbatim into the reviewer prompt. Delimiters are present, but the prompt does not establish a strict trust rule that content inside those delimiters is data only and must never be followed as instructions. The resulting prompt is sent to reviewers configured with disabled approval and sandbox protec ...[truncated 1421 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Run all review agents in a read-only sandbox with no shell, write, or credential access. - Add a high-priority instruction stating that PR content is untrusted data and that instructions inside the diff must never be followed. - Pass the diff through a dedicated data channel or structured attachment when the agent platform supports it. - Do not place untrusted diffs in the same instruction channel as operational commands. - Use a two-stage process: 1. A non-tool-enabled model summarizes the untrusted diff. 2. A separate constrained reviewer evaluates the summary and checked-out code. - Strip or separately flag suspicious instruction-like content in comments, documentation, and strings. - Use disposable review environments with no GitHub, SSH, cloud, or package-registry credentials. - Require deterministic user approval before any reviewer can invoke a command or modify a file. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/dev-board/apps/api/src/server.js:1414
Finding
Unauthenticated Development Board Is Not Explicitly Restricted to Loopback<![CDATA[ ## Vulnerability Details **File Location**: `scripts/dev-board/apps/api/src/server.js:1414-1419, 1667-1737, 1762-1875, 1881-1905` **Vulnerability Type**: Unauthenticated network access to operational data and local actions **Risk Level**: High ### Vulnerable Code ```js const LOCAL_ACTIONS_ENABLED = process.env.ENABLE_LOCAL_ACTIONS === '1'; const ACTION_SCRIPT_ALLOWLIST = Object.freeze({ 'check-agents': 'check-agents.sh', cleanup: 'cleanup-worktrees.sh', 'ai-review': 'review-agent.sh', fixup: 'request-fixup.sh' }); ``` ```js async function runActionRoute(req, urlObj, res) { const action = urlObj.pathname.replace('/api/actions/', ''); if (req.method !== 'POST') { return json(res, 405, { error: 'method_not_allowed', message: 'Use POST', action }); } if (!LOCAL_ACTIONS_ENABLED) { return json(res, 501, { ok: false, action, error: 'local_actions_disabled' }); } const { skillDir, scriptPath } = resolveAllowedActionScript(action); // Arguments are constructed according to the selected action. const execResult = execLocalAction( action, scriptPath, args, { cwd: skillDir, timeoutMs } ); return json(res, 200, execResult); } ``` ```js if (urlObj.pathname === '/api/tasks') { return json(res, 200, { items: state.tasks }); } if (urlObj.pathname === '/api/queue') { const queue = loadQueueState({ activeTasks: state.tasks }); return json(res, 200, { items: queue.items, counts: queue.counts, sourcePath: queue.sourcePath }); } if ( urlObj.pathname.startsWith('/api/tasks/') && urlObj.pathname.endsWith('/log') ) { const taskId = decodeURIComponent(parts[3] || ''); const task = state.tasks.find( (t) => t.id === taskId || t.branch === taskId || t.tmuxSession === taskId ); const tail = tailFileWithMeta(task.logFile, lines); return json(res, 200, { taskId: task.id, logFile: task.logFile, content: tail. ...[truncated 2667 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Bind explicitly to loopback: ```js server.listen(PORT, '127.0.0.1'); ``` Consider a separate explicit option for non-loopback deployment. - Add authenticated sessions or bearer-token authentication to every API endpoint. - Require stronger, action-specific authorization for script-execution routes. - Implement CSRF protection and strict Origin/Host validation for browser-accessible actions. - Keep local actions disabled by default and require a randomly generated startup token when enabled. - Separate the read-only dashboard from the process capable of running scripts. - Redact prompts, absolute paths, command output, and sensitive log content from API responses. - Apply request rate limits and produce security logs for every action request. - Run the action service under a restricted account with a minimal environment. - Reject non-loopback clients unless secure remote access has been explicitly configured. ]]>

T08 · Insecure Dependencies

Error
Location
scripts/spawn-agent.sh:419
Finding
Automatic Package Installation Executes Repository-Controlled Lifecycle Scripts<![CDATA[ ## Vulnerability Details **File Location**: `scripts/spawn-agent.sh:419-425` **Vulnerability Type**: Unsafe dependency installation and lifecycle-script execution **Risk Level**: High ### Vulnerable Code ```bash # Install dependencies if [[ -f "$WORKTREE_DIR/package.json" ]]; then echo "Installing dependencies..." cd "$WORKTREE_DIR" pnpm install 2>/dev/null || npm install 2>/dev/null || echo "No dependencies to install" cd "$SKILL_DIR" fi ``` ### Technical Analysis Whenever the target worktree contains `package.json`, the spawning workflow automatically runs `pnpm install` or falls back to `npm install`. Package managers normally execute lifecycle hooks such as `preinstall`, `install`, and `postinstall`. Those hooks can be defined directly by the repository or supplied by dependencies. Consequently, merely spawning an agent for an untrusted repository can execute repository-controlled code before the AI agent begins its assigned work. The installation does not require explicit user approval, does not suppress scripts, does not require a frozen lockfile, and is not shown to run in a disposable sandbox. Redirecting standard error also obscures useful security and failure diagnostics. ### Attack Path 1. An attacker places a malicious lifecycle hook in the repository's `package.json`, or introduces a compromised dependency with an installation hook. 2. A user invokes `spawn-agent.sh` against that repository. 3. The script detects `package.json`. 4. It automatically runs `pnpm install` or `npm install`. 5. The package manager executes the malicious lifecycle hook. 6. The hook runs with the permissions and environment of the Skill runner, before normal agent isolation can provide any protection. ### Impact Assessment A malicious installation hook could read or modify user-accessible files, alter the worktree or Skill scripts, access inherited credentials, contact external services, install additional payloads, or tamper with subsequ ...[truncated 169 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not install dependencies automatically as part of agent spawning. - Require explicit user approval or a task policy that authorizes installation. - Run installation inside a disposable container or sandbox without host credentials. - Disable lifecycle scripts by default: ```bash pnpm install --ignore-scripts npm ci --ignore-scripts ``` - Require an existing lockfile and enforce immutable installation: ```bash pnpm install --frozen-lockfile --ignore-scripts npm ci --ignore-scripts ``` - Reject unexpected package-manager changes or lockfile regeneration. - Pin the package manager and dependency registry configuration. - Retain and review package-manager error output instead of suppressing it. - Use dependency integrity, provenance, and vulnerability checks before enabling any required lifecycle hook. - Maintain an explicit allowlist for projects or packages whose install scripts are permitted. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (70)

Ae1

High
Category
analysis-evasion
Content
- 禁止 SubAgent 在 `main/master` 上直接开发(`spawn-agent.sh` 已拦截)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 禁止 SubAgent 在 `main/master` 上直接开发(`spawn-agent.sh` 已拦截)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 禁止 SubAgent 在 `main/master` 上直接开发(`spawn-agent.sh` 已拦截)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 禁止 SubAgent 在 `main/master` 上直接开发(`spawn-agent.sh` 已拦截)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 禁止 SubAgent 在 `main/master` 上直接开发(`spawn-agent.sh` 已拦截)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 禁止 SubAgent 在 `main/master` 上直接开发(`spawn-agent.sh` 已拦截)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 结束后可自动触发 `cleanup-worktrees.sh` 与 `prune-history.sh`(避免 worktree / active-tasks 膨胀)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 结束后可自动触发 `cleanup-worktrees.sh` 与 `prune-history.sh`(避免 worktree / active-tasks 膨胀)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 结束后可自动触发 `cleanup-worktrees.sh` 与 `prune-history.sh`(避免 worktree / active-tasks 膨胀)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
./scripts/recommend-agent.sh --description "前端看板优化" --phase build
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
./scripts/recommend-agent.sh --description "前端看板优化" --phase build
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
./scripts/recommend-agent.sh --description "前端看板优化" --phase build
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `enqueue-task.sh`:主 Agent 添加任务到队列(`assets/tasks.json`)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `enqueue-task.sh`:主 Agent 添加任务到队列(`assets/tasks.json`)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `claim-task.sh`:认领一个 queued 任务并调用 `spawn-agent.sh` 派工
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `claim-task.sh`:认领一个 queued 任务并调用 `spawn-agent.sh` 派工
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

External Model or Provider Selection

High
Category
Excessive Agency
Content
## Codex

```bash
codex exec [OPTIONS] "prompt"
  --dangerously-bypass-approvals-and-sandbox
  -C, --cd <DIR>
```
Confidence
90% confidence
Finding
Skill selects an external model or provider that may use a different account or billing plan than the operator expects. Undisclosed model switches can cause unexpected cost or quota consumption.

Credential Access

High
Category
Privilege Escalation
Content
out = (proc.stdout or "") + (proc.stderr or "")
            if "Not logged in" in out:
                # Fallback: probe inside tmux because dev-team runs subagents in tmux and
                # some environments cannot read Keychain auth in non-interactive shells.
                if shutil.which("tmux"):
                    probe_session = f"teamdev-cursor-probe-{os.getpid()}"
                    probe_file = f"/tmp/{probe_session}.txt"
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
out = (proc.stdout or "") + (proc.stderr or "")
            if "Not logged in" in out:
                # Fallback: probe inside tmux because dev-team runs subagents in tmux and
                # some environments cannot read Keychain auth in non-interactive shells.
                if shutil.which("tmux"):
                    probe_session = f"teamdev-cursor-probe-{os.getpid()}"
                    probe_file = f"/tmp/{probe_session}.txt"
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
local cursor_status
            cursor_status=$(cursor agent status 2>&1 || true)
            if echo "$cursor_status" | grep -qi "not logged in"; then
                # 某些环境(非交互 shell / keychain 可见性差异)会误报未登录,tmux 场景再探测一次
                if command -v tmux >/dev/null 2>&1; then
                    local probe_session="teamdev-cursor-probe-$$"
                    local probe_file="/tmp/${probe_session}.txt"
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
97% confidence
Finding
The skill documents and encourages powerful operations including shell execution, file read/write, network access, environment interaction, git automation, PR creation, and auto-merge, but it declares no explicit tool scope or permission boundary. In an agent framework, this creates an over-privileged and ambiguous trust model: the orchestrator or subagents may be allowed to invoke dangerous capabilities without a manifest-level constraint, increasing the chance of destructive commands, credential misuse, or unintended repository changes.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The skill begins presenting operational instructions in Chinese from L010 onward, while other sections remain in English. This imposes a language expectation on users without opt-in or justification that the skill is only for a Chinese-speaking audience, which matches the language/locale policy violation criteria.

Context-Inappropriate Capability

Medium
Confidence
99% confidence
Finding
This configuration explicitly launches multiple coding agents with approval bypass and effectively unsandboxed modes, such as `--dangerously-bypass-approvals-and-sandbox`, `--dangerously-skip-permissions`, and Gemini `yolo` approvals with shell and file-write tools. In a skill whose purpose is orchestrating automated software development across multiple agents, these settings materially increase the chance of unauthorized shell execution, filesystem changes, secret exposure, destructive git operations, or supply-chain compromise if prompts, tasks, or upstream agent behavior are manipulated.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The natural-language descriptions for multiple agents are written only in Chinese, with no indication that language selection is optional or that the configuration is intended for a Chinese-only environment. This can violate a language/locale policy when users are not given a choice or explicit notice about the enforced locale.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The document is written as mandatory operating guidance for the main agent, and its instructions are presented only in Chinese. This creates a language/locale constraint for agent operation without any stated opt-in, alternative language, or justification for the restriction.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/dev-board/apps/api/src/server.js:1049