Back to skill

Security audit

OpenClaw Desktop Control

Security checks for vulnerabilities and agentic risk

Overview

This desktop automation skill is mostly coherent, but it gives broad control over the local desktop and unrestricted file read/write access without clear safeguards.

Install only if you intentionally want an agent to control your active desktop, capture screenshots, type into applications, open or close apps, and read or write local files as your user. Prefer using it in a VM or test account, avoid sensitive windows and secrets while it is active, and review automation scripts before running them.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (42)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The documented behavior does not fully match the advertised purpose: it includes file system read/write actions not disclosed in the description, and claims VNC/RDP support that appears unsubstantiated. In a remote desktop automation context, mismatched documentation is dangerous because users may authorize a skill for UI automation while overlooking that it can also modify files or rely on misleading transport assumptions.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The file read/write commands permit direct access to local files without any warning, approval workflow, or path limitation, making sensitive data theft and destructive modification straightforward. In this skill context, that is more dangerous because users may expect UI automation, not unrestricted filesystem access.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
91% confidence
Finding

Automation script execution can chain together arbitrary desktop actions at scale, including clicks, keystrokes, waits, and likely file interactions through the controller, without any user warning or safety validation. This increases the chance of stealthy destructive behavior, bulk data exfiltration, or unintended irreversible UI actions.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill declares broad tools (read, write, exec) but does not define any narrower tool scope such as permissions or allowed-tools, while the documentation clearly enables shell execution and file read/write operations. In a desktop-control skill, this increases risk because the capability set can be used to manipulate the host system and access sensitive data beyond what a user may infer from the metadata.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

bash
# Ubuntu/Debian
sudo apt-get install python3-pil python3-xlib scrot

# macOS
brew install pillow

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The screenshot and --base64 examples explicitly support AI analysis of desktop captures, but the documentation does not clearly warn that screenshots can contain passwords, tokens, personal data, or regulated information. In a desktop-control skill this is especially sensitive because whole-screen capture can silently exfiltrate far more information than a typical file read.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The automation and file-write functionality can perform destructive or unintended actions on a desktop or filesystem, yet the documentation lacks a clear warning about operational safety, confirmation requirements, or rollback considerations. Because this skill can drive mouse, keyboard, apps, and file writes, accidental or malicious misuse could cause data loss, unsafe system changes, or unauthorized actions under the current user's privileges.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The file’s human-readable instructions and comments are entirely in Chinese, which imposes a specific language on users without any opt-in or explanation. Under the policy, language-specific guidance is only acceptable when the skill offers a choice or clearly documents a justified regional constraint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script performs real mouse and keyboard automation to launch a terminal and start a text editor without any user confirmation, safety interlock, or environment validation. In a desktop-control skill, such actions can unexpectedly interfere with the user session, trigger unintended commands, or be repurposed for harmful local actions if the script is modified or run in the wrong context.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The controller exposes arbitrary file read and write primitives that are unrelated to merely controlling the desktop UI. In the context of a desktop automation skill, this materially broadens access to local data and persistence, enabling exfiltration of sensitive files or tampering with user content without any scope restriction.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · lib/desktop_controller.py (reported line 230)May include surrounding context.

python
x, y, w, h = region
            cmd = ['screencapture', '-x', '-R', f'{x},{y},{w},{h}', temp_path]

        subprocess.run(cmd, check=True)
        data = Path(temp_path).read_bytes()
        Path(temp_path).unlink()
        return data

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · lib/desktop_controller.py (reported line 250)May include surrounding context.

python
cmd = ['gnome-screenshot', '-f', temp_path]

        try:
            subprocess.run(cmd, check=True, capture_output=True)
        except (subprocess.CalledProcessError, FileNotFoundError):
            # Fallback to scrot
            if region:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · lib/desktop_controller.py (reported line 258)May include surrounding context.

python
cmd = ['gnome-screenshot', '-f', temp_path]

        try:
            subprocess.run(cmd, check=True, capture_output=True)
        except (subprocess.CalledProcessError, FileNotFoundError):
            # Fallback to scrot
            if region:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill performs screenshots, keyboard injection, mouse control, window activation, and app launch without any user-facing disclosure or runtime confirmation. Because the skill operates on the local desktop, silent execution significantly raises the chance of unauthorized actions, privacy exposure, and covert manipulation of the host session.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · lib/desktop_controller.py (reported line 282)May include surrounding context.

python
def mouse_move(self, x: int, y: int) -> None:
        """Move mouse to coordinates"""
        if self.platform == 'macos':
            subprocess.run(['cliclick', 'm:', f'{x},{y}'], check=False)
        elif self.platform == 'linux':
            subprocess.run(['xdotool', 'mousemove', str(x), str(y)], check=False)
        else:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · lib/desktop_controller.py (reported line 284)May include surrounding context.

python
if self.platform == 'macos':
            subprocess.run(['cliclick', 'm:', f'{x},{y}'], check=False)
        elif self.platform == 'linux':
            subprocess.run(['xdotool', 'mousemove', str(x), str(y)], check=False)
        else:
            # Windows - would need pyautogui or similar
            pass

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · lib/desktop_controller.py (reported line 298)May include surrounding context.

python
if self.platform == 'macos':
            btn = 'cl' if button == 'left' else 'cr'
            for _ in range(clicks):
                subprocess.run(['cliclick', btn], check=False)
        elif self.platform == 'linux':
            btn_map = {'left': '1', 'middle': '2', 'right': '3'}
            btn = btn_map.get(button, '1')

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · lib/desktop_controller.py (reported line 303)May include surrounding context.

python
btn_map = {'left': '1', 'middle': '2', 'right': '3'}
            btn = btn_map.get(button, '1')
            for _ in range(clicks):
                subprocess.run(['xdotool', 'click', btn], check=False)

    def mouse_drag(self, from_x: int, from_y: int, to_x: int, to_y: int,
                   button: str = "left") -> None:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · lib/desktop_controller.py (reported line 322)May include surrounding context.

python
btn_map = {'left': '1', 'middle': '2', 'right': '3'}
            btn = btn_map.get(button, '1')
            for _ in range(clicks):
                subprocess.run(['xdotool', 'click', btn], check=False)

    def mouse_drag(self, from_x: int, from_y: int, to_x: int, to_y: int,
                   button: str = "left") -> None:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · lib/desktop_controller.py (reported line 309)May include surrounding context.

python
button: str = "left") -> None:
        """Drag mouse"""
        if self.platform == 'linux':
            subprocess.run(['xdotool', 'mousemove', str(from_x), str(from_y),
                          'mousedown', '1', 'mousemove', str(to_x), str(to_y),
                          'mouseup', '1'], check=False)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · lib/desktop_controller.py (reported line 327)May include surrounding context.

python
def mouse_position(self) -> Tuple[int, int]:
        """Get mouse position"""
        if self.platform == 'linux':
            result = subprocess.run(['xdotool', 'getmouselocation'],
                                  capture_output=True, text=True, check=False)
            # Parse "x:123 y:456 screen:0 window:789"
            output = result.stdout.strip()

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · lib/desktop_controller.py (reported line 342)May include surrounding context.

python
def type_text(self, text: str, delay: Optional[float] = None) -> None:
        """Type text"""
        if self.platform == 'macos':
            subprocess.run(['cliclick', 't:', text], check=False)
        elif self.platform == 'linux':
            subprocess.run(['xdotool', 'type', text], check=False)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

Although this is not shell injection, it allows arbitrary caller-supplied text to be injected into the active desktop context with no trust boundary, confirmation, or field targeting. In a remote desktop-control skill, this can be abused to enter commands, secrets, or approvals into privileged applications and materially increases the risk of unintended system actions.

Content

Scanner excerpt · lib/desktop_controller.py (reported line 344)May include surrounding context.

python
if self.platform == 'macos':
            subprocess.run(['cliclick', 't:', text], check=False)
        elif self.platform == 'linux':
            subprocess.run(['xdotool', 'type', text], check=False)

    def key_press(self, keys: List[str]) -> None:
        """Press key combination"""

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · lib/desktop_controller.py (reported line 353)May include surrounding context.

python
if self.platform == 'linux':
            key_str = '+'.join(keys)
            subprocess.run(['xdotool', 'key', key_str], check=False)
        elif self.platform == 'macos':
            # Convert to cliclick format
            key_map = {

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
72% confidence
Finding

This supports arbitrary key combinations assembled from caller-controlled input, enabling shortcuts such as launching terminals, invoking system dialogs, or confirming privileged actions. In context, broad keyboard automation without policy checks is dangerous because it can drive the host beyond simple UI assistance.

Content

Scanner excerpt · lib/desktop_controller.py (reported line 366)May include surrounding context.

python
'tab': 'tab'
            }
            key_str = ','.join([key_map.get(k, k) for k in keys])
            subprocess.run(['cliclick', 'kp:' + key_str], check=False)

    def key_down(self, key: str) -> None:
        """Hold key down"""