Back to skill

Security audit

Qqbot Installer

Security checks for vulnerabilities and agentic risk

Overview

This skill is an installer that can modify persistent OpenClaw plugins, but its generic package interface and unsafe script handling make it risky beyond a QQBot-only install.

Review this carefully before installing. Only run it with a known package and plugin ID, avoid the generic installer path, do not pass untrusted legacy directory names, and prefer a version with allowlists, integrity checks, safer rollback, and explicit confirmation before restart or postinstall execution.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/upgrade-plugin.sh:124
Finding

JavaScript Injection Through the Plugin Identifier

Content
View full analysis
/dev/null || true)" ``` ### Technical Analysis `PLUGIN_ID` is supplied as a positional command-line argument and is interpolated directly into JavaScript source passed to `node -e`. Shell quoting does not protect the JavaScript string itself. An attacker-controlled plugin identifier containing quotes and JavaScript syntax can terminate the property-access expression and introduce arbitrary Node.js instructions. Node.js exposes operating-system APIs such as `child_process`, so successful JavaScript injection can be converted directly into arbitrary shell command execution. The surrounding `try/catch` does not prevent exploitation; it only suppresses errors produced while the injected program is evaluated. `CONFIG_FILE` is interpolated into the same JavaScript source and could present a similar problem if an attacker can influence the discovered configuration path. ### Attack Path 1. An attacker convinces the Agent or user to invoke the generic installer with a crafted `plugin-id`. 2. The script accepts the identifier without syntax validation. 3. The identifier is inserted into the program supplied to `node -e`. 4. The crafted value terminates the intended JavaScript string or expression and injects additional JavaScript. 5. The injected JavaScript imports `child_process` or uses another Node.js execution primitive. 6. Arbitrary operating-system commands execute with the privileges of the account running the Skill. ### Impact Assessment Successful exploitation provid ...[truncated 403 chars]
Remediation
View remediation
/dev/null || true)" ``` Additionally: 1. Validate `PLUGIN_ID` before using it. If plugin IDs are intended to be directory names, enforce a narrow allowlist such as `^[A-Za-z0-9._-]+$`. 2. Reject empty identifiers, path separators, control characters, quotes, and traversal components. 3. Apply the same argument-passing design to every `node -e` invocation involving dynamic paths. 4. Add tests using identifiers containing quotes, newlines, semicolons, backticks, and JavaScript syntax. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/upgrade-plugin.sh:165
Finding

Arbitrary Directory Deletion Through Traversal in Legacy Directory Names

Content
View full analysis
Remediation
View remediation
&2 exit 1 fi TARGET="$BASE_DIR/$d" if [ -d "$TARGET" ]; then RESOLVED_TARGET="$(realpath -- "$TARGET")" case "$RESOLVED_TARGET" in "$BASE_DIR"/*) rm -rf -- "$RESOLVED_TARGET" ;; *) echo "Refusing to delete path outside extensions directory" >&2; exit 1 ;; esac fi done ``` Where possible, replace permanent recursive deletion with a reversible quarantine or rename operation. ]]>

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/upgrade-plugin.sh:173
Finding

Installation and Execution of Unverified Remote npm Package Code

Content
View full analysis
&1; then UPGRADE_OK=true echo " ✅ install 成功" [ -n "$BACKUP_DIR" ] && [ -d "$BACKUP_DIR" ] && rm -rf "$BACKUP_DIR" && echo " 已清理旧版备份" else echo " ❌ install 失败" [ -n "$BACKUP_DIR" ] && [ -d "$BACKUP_DIR" ] && mv "$BACKUP_DIR" "$EXTENSIONS_DIR/$PLUGIN_ID" && echo " ↩️ 已回滚" exit 1 fi ``` A package-controlled JavaScript file is then explicitly executed: ```bash # 执行 postinstall 脚本(如有) POSTINSTALL="$TARGET_DIR/scripts/postinstall-link-sdk.js" if [ -f "$POSTINSTALL" ]; then echo " 执行 postinstall-link-sdk..." node "$POSTINSTALL" 2>&1 && echo " ✅ plugin-sdk 链接就绪" || echo " ⚠️ postinstall 失败,插件可能无法加载" fi ``` The generic interface is documented in `SKILL.md`, lines 66-72: ```bash bash /scripts/upgrade-plugin.sh \ "my-org/my-openclaw-plugin" \ "my-plugin-id" ``` ### Technical Analysis The package name is caller-controlled, and an unspecified version defaults to `latest`. The script delegates retrieval and installation to the OpenClaw CLI without enforcing: - An allowlist of approved package names - An approved registry - An exact audited version - A package integrity digest - A cryptographic signature or provenance policy - A review of the downloaded executable files The `--pin` option may record the selected package version, but it does not establish that the package was trustworthy before installation. The effective payload can change after this Skill has been reviewed because the remote package or its `latest` tag is controlled outside the audited project. After installation, the script explicitly runs `scripts/postinstall-link-sdk.js` fro ...[truncated 1737 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/upgrade-plugin.sh:152
Finding

Backup Is Destroyed Before Installation Validation Completes

Content
View full analysis
&1; then UPGRADE_OK=true echo " ✅ install 成功" [ -n "$BACKUP_DIR" ] && [ -d "$BACKUP_DIR" ] && rm -rf "$BACKUP_DIR" && echo " 已清理旧版备份" else echo " ❌ install 失败" [ -n "$BACKUP_DIR" ] && [ -d "$BACKUP_DIR" ] && mv "$BACKUP_DIR" "$EXTENSIONS_DIR/$PLUGIN_ID" && echo " ↩️ 已回滚" exit 1 fi ``` Validation occurs only after the successful-install branch has already deleted the backup: ```bash if [ "$VERIFY_OK" != "true" ]; then echo "" echo "❌ 验证未通过" exit 1 fi ``` ### Technical Analysis The previous plugin directory is initially moved to a backup location. However, as soon as the installation command returns success, the backup is permanently deleted. Package validation, required-file checks, package-controlled post-install execution, and gateway restart all occur afterward. Consequently, a successful installer exit does not represent a completed safe transaction. A package may install successfully but contain a missing or invalid `package.json`, omit required files, fail its helper script, or fail when loaded. In these cases, the known-good plugin has already been destroyed and cannot be restored by the script. This behavior contradicts the documented automatic rollback expectation and gives malicious or malformed package content an opportun ...[truncated 1193 chars]
Remediation
View remediation
Vulnerability Patterns
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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 (7)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 56)May include surrounding context.

md
> `<skill_dir>` = 本 skill 文件所在目录,即 `SKILL.md` 的 dirname。

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
96% confidence
Finding

The script deletes paths derived from the user-controlled --legacy-dirs parameter using rm -rf without validating that each entry is a simple child directory name. An attacker can supply values like '..' or path-like segments to cause deletion outside the intended plugin directory, leading to arbitrary file or directory removal within the privileges of the script.

Content

Scanner excerpt · scripts/upgrade-plugin.sh (reported line 157)May include surrounding context.

sh
if [ -n "$LEGACY_DIRS" ]; then
        IFS=',' read -ra LDIRS <<< "$LEGACY_DIRS"
        for d in "${LDIRS[@]}"; do
            [ -d "$EXTENSIONS_DIR/$d" ] && rm -rf "$EXTENSIONS_DIR/$d" && echo "  已清理历史目录: $d"
        done
    fi

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · scripts/upgrade-plugin.sh (reported line 157)May include surrounding context.

sh
if [ -n "$LEGACY_DIRS" ]; then
        IFS=',' read -ra LDIRS <<< "$LEGACY_DIRS"
        for d in "${LDIRS[@]}"; do
            [ -d "$EXTENSIONS_DIR/$d" ] && rm -rf "$EXTENSIONS_DIR/$d" && echo "  已清理历史目录: $d"
        done
    fi

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · scripts/upgrade-plugin.sh (reported line 164)May include surrounding context.

sh
if [ -n "$LEGACY_DIRS" ]; then
        IFS=',' read -ra LDIRS <<< "$LEGACY_DIRS"
        for d in "${LDIRS[@]}"; do
            [ -d "$EXTENSIONS_DIR/$d" ] && rm -rf "$EXTENSIONS_DIR/$d" && echo "  已清理历史目录: $d"
        done
    fi

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The activation phrase list includes broad natural-language patterns such as asking how to install or help installing/upgrading qqbot, which can overlap with ordinary discussion rather than an explicit consent to execute system changes. In a skill that performs installation, upgrade, rollback, and restart actions, overbroad triggering increases the chance of unintended privileged operations being launched from casual conversation or adversarially crafted prompts.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill is presented as a QQBot-specific installer, but it explicitly documents a generic invocation that can install arbitrary plugins by package name and plugin ID. In an agent context, this creates a capability expansion: a user or prompt injection could repurpose the skill to install unreviewed code beyond the stated scope, leading to arbitrary code execution via plugin install/postinstall paths and persistent compromise of the OpenClaw environment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This shell script includes its descriptive comments, usage text, and runtime messages entirely in Chinese. That imposes a specific language on users without offering an alternative or documenting a justified locale restriction, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.