Back to skill

Security audit

maxclaw-doctor

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent file-versioning helper, but it needs review because its setup instructions can run unverified system installers and its file operations are not constrained to the project.

Install only if you are comfortable with a local tool that can copy, move, restore, and retain files available to your user account. Do not let an agent run the Homebrew curl-to-bash commands, sudo package installs, or shell-profile edits without separate review. Use it only on an explicit project directory, avoid sensitive files such as secrets and credentials, and verify cleanup of ~/.openclaw/minivcs when records are no longer needed.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (2)

T03 · Remote Payload Retrieval and Execution

Error
Location
SKILL.md:57
Finding

Mutable Remote Installation Scripts Are Downloaded and Executed Directly

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 57–66
Vulnerability Type: Remote payload retrieval and immediate shell execution
Risk Level: Critical

Vulnerable Code

bash
# No Homebrew: install Homebrew first
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install python3
bash
# Install Homebrew using the Tsinghua University mirror
/bin/bash -c "$(curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/install.sh)"

Technical Analysis

The Skill instructs the agent to retrieve shell scripts from external URLs and pass the responses directly to /bin/bash. The downloaded content is not pinned to an immutable version and is not validated using a cryptographic signature or a trusted checksum before execution.

In particular, the GitHub URL references the mutable HEAD branch. Consequently, the code that is ultimately executed can change after this Skill has been reviewed. The mirror endpoint is also trusted without independent integrity verification.

This behavior creates an external code-execution channel. Installing Homebrew is also broader than the Skill's declared file-versioning functionality and is unnecessary when a suitable Python 3 interpreter is already available. Although the instructions condition this path on Python being absent, the installation mechanism still exceeds the minimum privileges and trust required to implement local file tracking.

Attack Path

  1. The Skill checks the environment and determines that Python 3 is unavailable or not discoverable in PATH.
  2. The agent follows the installation instructions in SKILL.md.
  3. curl retrieves the current response from GitHub or the configured mirror.
  4. Command substitution places the unverified response directly into a Bash invocation.
  5. If the remote repository, hosting account, mirror, DNS/TLS trust path, or distributed installer is c ...[truncated 816 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove all curl | bash and command-substitution-based remote execution instructions.
  2. Prefer directing the user to an official, interactive installer and require explicit confirmation before installing unrelated system tooling.
  3. If automated installation is essential:
    • Pin the installer to an immutable, reviewed release or commit.
    • Download it to a local file without executing it.
    • Verify a publisher-provided cryptographic signature or a securely distributed checksum.
    • Display the source and planned command to the user.
    • Execute it only after explicit approval.
  4. Prefer an existing Python interpreter or a narrowly scoped Python installation method over installing a general-purpose package manager.
  5. Do not automatically grant elevated privileges. Clearly identify any commands that may request administrator access.
  6. Treat mirror configuration as optional and require separate consent before changing persistent shell configuration.

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/minivcs/minivcs.py:418
Finding

File Operations Are Not Restricted to the Declared Project Root

Content
View full analysis

Vulnerability Details

File Location: scripts/minivcs/minivcs.py, lines 418–570 and 616–665
Vulnerability Type: Missing filesystem scope and path-containment enforcement
Risk Level: Medium

Vulnerable Code

python
def __init__(self, project_root: str, vcs_root: Optional[str] = None):
    self.project_root = os.path.abspath(project_root)
    # Default storage under ~/.openclaw/minivcs/, separate from project directory
    if vcs_root is not None:
        self.vcs_root = os.path.abspath(vcs_root)
    else:
        self.vcs_root = os.path.join(os.path.expanduser("~"), ".openclaw", "minivcs")
    self.log_manager = LogManager(self.vcs_root)
    self.diff_engine = DiffEngine()
    self.file_manager = FileManager(self.vcs_root, self.project_root)

def _get_relative_path(self, absolute_path: str) -> str:
    if absolute_path.startswith(self.project_root + os.sep):
        return absolute_path[len(self.project_root) + 1 :]
    return absolute_path
python
abs_path = os.path.abspath(file_path)
if not os.path.exists(abs_path):
    return {"success": False, "error": f"File not found: {file_path}"}
python
def record_delete(self, file_path: str) -> Dict[str, Any]:
    """
    Record deletion by moving the file into trash.
    """
    abs_path = os.path.abspath(file_path)
    if not os.path.exists(abs_path):
        return {"success": False, "error": f"File not found: {file_path}"}

    try:
        relative_path = self._get_relative_path(abs_path)
        important = is_important_file(abs_path)
        retention_days = get_retention_days(abs_path)

        trash_path = self.file_manager.save_to_trash(abs_path)
python
file_path = record.get("filePath", "")
target_path = file_path if os.path.isabs(file_path) else os.path.join(self.project_root, file_path)

Technical Analysis

project_root is used to calculate relative paths, but it i ...[truncated 2699 chars]

Remediation
View remediation

Remediation Suggestions

  1. Canonicalize both the project root and candidate path with os.path.realpath() before every read, move, copy, delete, or restore operation.
  2. Enforce containment using os.path.commonpath() rather than string-prefix comparison. Reject the operation unless the canonical candidate is inside the canonical project root.
  3. Reject symbolic links whose resolved targets leave the project. Where possible, use file-descriptor-based operations and no-follow semantics to reduce time-of-check/time-of-use risks.
  4. Require a separate, explicit user opt-in for operations outside the project root. Display the canonical target path before confirmation.
  5. Apply the same validation to paths loaded from logs.json; stored records must not be treated as trusted authorization data.
  6. Restrict vcs_root to a controlled directory and verify that artifact paths from records remain inside it before deleting or restoring them.
  7. Store backups with restrictive permissions and consider encryption or redaction because snapshots may contain secrets.
  8. Add automated tests for:
    • Absolute paths outside the project.
    • .. traversal.
    • Symlinks pointing outside the project.
    • Crafted or modified record paths.
    • Restoration to external locations.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (12)

Chaining Abuse

High
Category
Tool Misuse
Confidence
83% confidence
Finding

The chained command combines update and install in a single privileged shell expression, reducing opportunities for review between steps. In agent-mediated environments, command chaining can make it easier to smuggle or overlook unsafe actions, and it amplifies consequences because both operations run under sudo in sequence.

Content

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

Linux(Debian / Ubuntu)

bash
sudo apt update && sudo apt install -y python3 python3-pip

Linux(CentOS / RHEL / Fedora)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/minivcs/minivcs.py (reported line 44)May include surrounding context.

python
".ini",
    ".cfg",
    ".conf",
    ".env",
    # 常见入口文件名(精确匹配)
    "main.py",
    "app.py",

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill describes concrete file read/write capabilities and shell/Python operations that can modify, delete, restore, and back up files, but it declares no explicit tool scope or permissions boundary. In an agent setting, missing scope metadata increases the risk that the runtime grants broader filesystem access than users expect, especially because the skill is designed to operate on arbitrary paths and home-directory storage.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill documentation is written entirely in Chinese and all example user-facing prompts are specified only in Chinese, which implies a fixed language/locale expectation. There is no statement offering users a language choice or limiting the skill to a China-specific deployment context, so this conflicts with the policy against forcing a specific language without opt-in.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
89% confidence
Finding

The skill instructs use of sudo to install software, which normalizes privileged execution inside an agent workflow. If followed automatically or with insufficient scrutiny, this can lead to unintended system-wide changes and expands the blast radius of any mistake or malicious substitution in adjacent commands or package sources.

Content

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

Linux(Debian / Ubuntu)

bash
sudo apt update && sudo apt install -y python3 python3-pip

Linux(CentOS / RHEL / Fedora)

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
88% confidence
Finding

This line recommends sudo-based package installation on CentOS/RHEL, again encouraging root-level changes as part of routine skill usage. In the context of a file-management skill, elevated package-management steps are broader than necessary and can be abused or misapplied on sensitive hosts.

Content

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

bash
# CentOS / RHEL
sudo yum install -y python3

# Fedora
sudo dnf install -y python3

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
88% confidence
Finding

The Fedora installation command also uses sudo and carries the same risk profile: unnecessary normalization of privileged execution for a skill whose core purpose is file tracking. On systems with sensitive workloads, encouraging root package changes can introduce avoidable operational and security risk.

Content

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

sudo yum install -y python3

Fedora

sudo dnf install -y python3

text

#### Windows

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

L164 明确要求告知用户二进制文件“不会被记录,需用户自行保管”,但 L021、L151、L347、L357 又说明二进制文件会保存 .bak 完整副本,且记录类型为 BINARY_BACKUP。这不是单纯遗漏,而是对该技能是否保护/记录二进制文件的核心意图产生直接冲突,可能误导用户对文件保护范围的理解。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module docstring and most user-facing descriptions are written only in Chinese, which imposes a specific language/locale in the skill's natural-language interface. There is no indication that the user can choose another language or that this locale restriction is documented as an intentional region-specific limitation.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The importance classifier explicitly treats the entire home directory, system configuration paths, and Windows C: paths as special files to retain longer. While this does not itself grant new OS permissions, it normalizes and supports handling sensitive files well outside the project scope, making accidental backup, retention, and later restoration of secrets or system files more likely.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The tool accepts arbitrary file paths and only uses project_root to compute a relative display path; it does not enforce that operations stay داخل the intended project boundary. As a result, an agent using this skill can record, delete, restore, or roll back files anywhere on the filesystem, which exceeds the stated purpose of protecting files used with openclaw and increases the blast radius to sensitive host files.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The record_modify docstring says rollback works by calling the recorder once after each edit, where the previous base is saved as the pre-edit snapshot. But the restore error message states rollback is only possible when record_modify was called both before and after the edit, which contradicts the documented and implemented workflow and misrepresents the skill's behavior.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.