Back to skill

Security audit

Mu Pet

Security checks for vulnerabilities and agentic risk

Overview

This desktop pet is mostly purpose-aligned, but its persistent Electron app exposes unsafe local control paths that could let another local process run code as the user.

Review carefully before installing. This skill installs a persistent macOS Electron app and exposes a local API; as written, another local process could abuse that API to inject code into the app. Prefer a version that removes executeJavaScript, renders bubble text safely, disables Node integration, authenticates or replaces the local API, pins dependencies with a lockfile, and makes auto-start optional.

Vulnerability Patterns
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T06 · System Persistence

Warning
Location
scripts/install.sh:20
Finding

Unconditional Login Persistence Through a KeepAlive LaunchAgent

Content
View full analysis
"$PLIST" << EOF Labelai.openclaw.desktop-pet ProgramArguments $APP_DEST/node_modules/.bin/electron $APP_DEST WorkingDirectory$APP_DEST RunAtLoad KeepAlive StandardOutPath/tmp/desktop-pet.log StandardErrorPath/tmp/desktop-pet.log EnvironmentVariables PATH/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin EOF # Load it launchctl unload "$PLIST" 2>/dev/null || true launchctl load "$PLIST" ``` ### Technical Analysis The installer always creates and loads a user LaunchAgent. `RunAtLoad` starts the Electron application when the user logs in, while `KeepAlive` directs macOS to restart it after termination. Auto-launch is documented in `SKILL.md`, and `scripts/uninstall.sh` removes the LaunchAgent. Therefore, the mechanism is not hidden and is related to an always-available desktop companion. Nevertheless, persistence is not necessary for the pet's core functionality, which can run directly through Electron. Enabling it unconditionally during installation exceeds minimum privilege and lifecycle requirements. The use of `KeepAlive` is particularly intrusive: selecting “Quit” in the application's context menu may not produce a durable shutdown because the service manager can restart the process. ### Attack Path 1. The user runs `scripts/install.sh`. 2. Th ...[truncated 951 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
assets/app/main.js:18
Finding

Arbitrary JavaScript and OS Command Execution Through the Local State API

Content
View full analysis
{ const { state, status, bubble, duration } = req.body || {}; if (win && !win.isDestroyed() && state) { const text = (bubble || status || '').replace(/"/g, '\\"').replace(/\n/g, ' '); const dur = duration || 0; win.webContents.executeJavaScript(`window.setState("${state}", "${text}", ${dur})`); res.json({ ok: true, state, bubble: text }); } else { res.status(400).json({ error: 'need state' }); } }); ``` ```javascript webPreferences: { nodeIntegration: true, contextIsolation: false, } ``` The server is exposed without authentication: ```javascript apiServer = api.listen(18891, '127.0.0.1', () => { console.log('Mu API: http://127.0.0.1:18891'); }); ``` ### Technical Analysis Values obtained from an unauthenticated HTTP request are interpolated into source code passed to `webContents.executeJavaScript`. This is a code-injection sink rather than a structured message channel. The `state` field is inserted inside a quoted JavaScript string without any escaping. The `text` field only escapes double quotes and line feeds; it does not safely handle backslashes, carriage returns, Unicode line separators, or other syntax-breaking content. The `duration` field is inserted as a raw JavaScript expression without numeric type validation. An attacker can terminate the expected expression and append arbitrary JavaScript. This becomes an operating-system command execution issue because the renderer has `nodeIntegration: true` and `contextIsolation: false`. Injected renderer code can use Node.js modules such as `child_process` with the privileges of the logged-in user. Binding the API to `127.0.0.1` reduces network exposure but does not provide authorizati ...[truncated 1624 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
assets/app/index.html:159
Finding

HTML Injection in API-Controlled Speech Bubbles

Content
View full analysis
'; bubble.classList.add('show'); if (bubbleTimer) clearTimeout(bubbleTimer); bubbleTimer = setTimeout(() => bubble.classList.remove('show'), dur || 3000); } ``` The affected renderer imports Electron directly: ```javascript const { ipcRenderer } = require('electron'); ``` ### Technical Analysis `showBubble` assigns externally controllable text to `innerHTML`. The `bubble` or `status` value supplied to `POST /state` reaches `setState`, which calls `showBubble`. Consequently, the application parses attacker-controlled content as HTML instead of displaying it as text. Although injected `
Remediation
View remediation
bubble.classList.remove('show'), dur || 3000 ); } ``` 3. Enforce server-side type and length validation for bubble text. 4. Disable Node integration and enable context isolation and renderer sandboxing. 5. Add a restrictive Content Security Policy as defense in depth, while recognizing that CSP is not a substitute for safe DOM construction. 6. Add tests containing HTML tags, event-handler attributes, quotes, backslashes, and Unicode separators to verify that all messages are rendered exclusively as text. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/install.sh:15
Finding

Unpinned and Non-Reproducible Production Dependency Installation

Content
View full analysis
&1 | tail -3 ``` From `assets/app/package.json`: ```json "dependencies": { "electron": "^35.0.0", "express": "^4.21.0" } ``` No package lockfile is present in the audited directory structure. ### Technical Analysis The installer performs a production `npm install` using mutable caret version ranges and without a committed lockfile. Installation is therefore not reproducible: a future invocation may resolve dependency or transitive dependency versions different from those reviewed during the audit. This is a supply-chain weakness rather than proof that either declared package is malicious. The observed package names are consistent with the application's stated functionality. The risk arises because package contents can change between installations, transitive dependency resolution is not fixed, and npm lifecycle scripts may run during installation. Piping output through `tail -3` also hides most installation diagnostics, making warnings and unexpected lifecycle activity less visible to the user. ### Attack Path 1. The user runs `scripts/install.sh`. 2. `npm install --production` contacts the configured npm registry. 3. npm resolves versions allowed by the caret ranges and resolves their transitive dependency trees. 4. A newly published, compromised, or otherwise unreviewed allowed version is downloaded. 5. Any permitted package lifecycle scripts execute with the user's privileges during installation. 6. The resolved code is stored in the directory referenced by the persistent LaunchAgent. 7. The LaunchAgent subsequently starts that dependency code and may keep it running across sessions. ### Impact Assessment A compromise ...[truncated 480 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (29)

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

Hit the API at the start of responses to make the pet face the user:

bash
curl -s -X POST http://127.0.0.1:18891/state \
  -H 'Content-Type: application/json' \
  -d '{"state":"talking","bubble":"working on it..."}'

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The renderer assigns untrusted text to bubble.innerHTML, so any attacker-controlled statusText can inject arbitrary HTML into the Electron renderer. In this skill, the pet state is updated via a local API and exposed window.setState, which makes the issue more dangerous than a normal web UI because injected markup could alter the overlay UI, load remote resources, or become script execution if Electron/browser settings are permissive elsewhere.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The manifest describes a visual desktop pet overlay that reacts to cursor, screen edges, active windows, and local API state changes. While avoiding active windows is in scope, the implementation achieves this by invoking osascript via child_process.execSync, which is a stronger host-execution capability than the manifest suggests and reaches into other applications through macOS automation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

Although the subprocess use appears functionally related to the pet's window-avoidance feature, it invokes AppleScript/System Events to inspect the frontmost application window without any visible disclosure or consent flow. This can surprise users and expands the skill's observational access to other apps, creating privacy and trust risk even if the collected data is limited to window geometry.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The installer creates and immediately loads a per-user LaunchAgent with RunAtLoad and KeepAlive, causing the app to persist across logins without an explicit opt-in or separate confirmation step. For a desktop mascot this may be intended functionality, but silently establishing persistence is security-relevant because it makes ongoing execution easy to miss and normalizes autorun behavior.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
95% confidence
Finding

Beginning at this point, the script writes a LaunchAgent plist into ~/Library/LaunchAgents, which is a standard macOS persistence mechanism. In the context of a desktop pet, persistence may be expected, but creating it automatically during install still has security implications because it causes ongoing background execution after the initial run.

Content

Scanner excerpt · scripts/install.sh (reported line 23)May include surrounding context.

sh
npm install --production 2>&1 | tail -3

# Create LaunchAgent
cat > "$PLIST" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>

Session Persistence

Medium
Category
Rogue Agent
Confidence
95% confidence
Finding

This duplicate finding refers to the same LaunchAgent creation block that installs persistence under the user account. The persistence is likely product-driven rather than malicious, but still constitutes a real security-relevant behavior.

Content

Scanner excerpt · scripts/install.sh (reported line 25)May include surrounding context.

sh
# Create LaunchAgent
cat > "$PLIST" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
  <key>Label</key><string>ai.openclaw.desktop-pet</string>
  <key>ProgramArguments</key><array>

Session Persistence

Medium
Category
Rogue Agent
Confidence
95% confidence
Finding

This duplicate finding refers to the same LaunchAgent creation block that installs persistence under the user account. The persistence is likely product-driven rather than malicious, but still constitutes a real security-relevant behavior.

Content

Scanner excerpt · scripts/install.sh (reported line 25)May include surrounding context.

sh
# Create LaunchAgent
cat > "$PLIST" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
  <key>Label</key><string>ai.openclaw.desktop-pet</string>
  <key>ProgramArguments</key><array>

Session Persistence

Medium
Category
Rogue Agent
Confidence
94% confidence
Finding

The plist declaration continues the setup of a login-persistent Electron process. Persistent Electron apps expand the attack surface over time because they remain available across sessions and may silently restart if terminated.

Content

Scanner excerpt · scripts/install.sh (reported line 26)May include surrounding context.

sh
cat > "$PLIST" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
  <key>Label</key><string>ai.openclaw.desktop-pet</string>
  <key>ProgramArguments</key><array>
    <string>$APP_DEST/node_modules/.bin/electron</string>

Session Persistence

Medium
Category
Rogue Agent
Confidence
89% confidence
Finding

Although this line is near the end of the plist body, it remains part of the same persistent LaunchAgent configuration. The broader risk is sustained background execution rather than this specific PATH setting.

Content

Scanner excerpt · scripts/install.sh (reported line 40)May include surrounding context.

sh
<key>EnvironmentVariables</key><dict>
    <key>PATH</key><string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
  </dict>
</dict></plist>
EOF

# Load it

Session Persistence

Medium
Category
Rogue Agent
Confidence
97% confidence
Finding

This line unloads any existing LaunchAgent and prepares to replace it, which is part of maintaining persistence. Replacing an existing user agent without prompting can mask changes in behavior and reinforces silent autorun installation.

Content

Scanner excerpt · scripts/install.sh (reported line 44)May include surrounding context.

sh
EOF

# Load it
launchctl unload "$PLIST" 2>/dev/null || true
launchctl load "$PLIST"

echo "🦞 Desktop Pet installed and running!"

Session Persistence

Medium
Category
Rogue Agent
Confidence
94% confidence
Finding

This duplicate match points to the same immediate activation of the LaunchAgent. The skill context makes persistence somewhat more expected than in unrelated software, but less dangerous context does not eliminate the security significance of silent autorun.

Content

Scanner excerpt · scripts/install.sh (reported line 45)May include surrounding context.

sh
# Load it
launchctl unload "$PLIST" 2>/dev/null || true
launchctl load "$PLIST"

echo "🦞 Desktop Pet installed and running!"
echo "   App: $APP_DEST"

Session Persistence

Medium
Category
Rogue Agent
Confidence
94% confidence
Finding

This duplicate match points to the same immediate activation of the LaunchAgent. The skill context makes persistence somewhat more expected than in unrelated software, but less dangerous context does not eliminate the security significance of silent autorun.

Content

Scanner excerpt · scripts/install.sh (reported line 45)May include surrounding context.

sh
# Load it
launchctl unload "$PLIST" 2>/dev/null || true
launchctl load "$PLIST"

echo "🦞 Desktop Pet installed and running!"
echo "   App: $APP_DEST"

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

md
#!/bin/bash
# Uninstall desktop-pet
set -e
PLIST="$HOME/Library/LaunchAgents/ai.openclaw.desktop-pet.plist"
APP_DEST="$HOME/.openclaw/desktop-pet"

echo "🦞 Uninstalling Desktop Pet..."

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

md
#!/bin/bash
# Uninstall desktop-pet
set -e
PLIST="$HOME/Library/LaunchAgents/ai.openclaw.desktop-pet.plist"
APP_DEST="$HOME/.openclaw/desktop-pet"

echo "🦞 Uninstalling Desktop Pet..."

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

md
#!/bin/bash
# Uninstall desktop-pet
set -e
PLIST="$HOME/Library/LaunchAgents/ai.openclaw.desktop-pet.plist"
APP_DEST="$HOME/.openclaw/desktop-pet"

echo "🦞 Uninstalling Desktop Pet..."

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

md
#!/bin/bash
# Uninstall desktop-pet
set -e
PLIST="$HOME/Library/LaunchAgents/ai.openclaw.desktop-pet.plist"
APP_DEST="$HOME/.openclaw/desktop-pet"

echo "🦞 Uninstalling Desktop Pet..."

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/install.sh (reported line 8)May include surrounding context.

sh
#!/bin/bash
# Uninstall desktop-pet
set -e
PLIST="$HOME/Library/LaunchAgents/ai.openclaw.desktop-pet.plist"
APP_DEST="$HOME/.openclaw/desktop-pet"

echo "🦞 Uninstalling Desktop Pet..."

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/uninstall.sh (reported line 4)May include surrounding context.

sh
#!/bin/bash
# Uninstall desktop-pet
set -e
PLIST="$HOME/Library/LaunchAgents/ai.openclaw.desktop-pet.plist"
APP_DEST="$HOME/.openclaw/desktop-pet"

echo "🦞 Uninstalling Desktop Pet..."

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

md
#!/bin/bash
# Uninstall desktop-pet
set -e
PLIST="$HOME/Library/LaunchAgents/ai.openclaw.desktop-pet.plist"
APP_DEST="$HOME/.openclaw/desktop-pet"

echo "🦞 Uninstalling Desktop Pet..."

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/install.sh (reported line 8)May include surrounding context.

sh
#!/bin/bash
# Uninstall desktop-pet
set -e
PLIST="$HOME/Library/LaunchAgents/ai.openclaw.desktop-pet.plist"
APP_DEST="$HOME/.openclaw/desktop-pet"

echo "🦞 Uninstalling Desktop Pet..."

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/uninstall.sh (reported line 4)May include surrounding context.

sh
#!/bin/bash
# Uninstall desktop-pet
set -e
PLIST="$HOME/Library/LaunchAgents/ai.openclaw.desktop-pet.plist"
APP_DEST="$HOME/.openclaw/desktop-pet"

echo "🦞 Uninstalling Desktop Pet..."

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/uninstall.sh (reported line 8)May include surrounding context.

sh
#!/bin/bash
# Uninstall desktop-pet
set -e
PLIST="$HOME/Library/LaunchAgents/ai.openclaw.desktop-pet.plist"
APP_DEST="$HOME/.openclaw/desktop-pet"

echo "🦞 Uninstalling Desktop Pet..."

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/uninstall.sh (reported line 9)May include surrounding context.

sh
#!/bin/bash
# Uninstall desktop-pet
set -e
PLIST="$HOME/Library/LaunchAgents/ai.openclaw.desktop-pet.plist"
APP_DEST="$HOME/.openclaw/desktop-pet"

echo "🦞 Uninstalling Desktop Pet..."

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
assets/app/main.js:108