Back to skill

Security audit

Pixel Lobster Skill

Security checks for vulnerabilities and agentic risk

Overview

This is mostly a real desktop avatar skill, but it needs Review because its optional system-audio mode can monitor all system playback and auto-grants broad media permissions.

Review this carefully before installing. Use the default tts mode if you only want OpenClaw speech lip sync. Do not enable system audio unless you are comfortable with the app accessing all system playback, and review/pin npm dependencies before running the helper script or npm install.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T08 · Insecure Dependencies

Warning
Location
app/package.json:13
Finding
Unpinned Electron Dependency and Automatic Package Installation<![CDATA[ ## Vulnerability Details **File Location**: `app/package.json:13-15`, `scripts/launch.sh:22-25`, `SKILL.md:29-33` **Vulnerability Type**: Unpinned third-party dependency and non-reproducible installation **Risk Level**: Medium ### Vulnerable Code `app/package.json:13-15`: ```json "devDependencies": { "electron": "^34.0.0" } ``` `scripts/launch.sh:22-25`: ```bash if [ ! -d "node_modules" ]; then echo "Installing dependencies (first run only)..." npm install fi ``` `SKILL.md:29-33`: ```bash cd <skill_dir>/app npm install ``` ### Technical Analysis The project does not include a dependency lockfile and declares Electron using the mutable version range `^34.0.0`. Consequently, separate installations can resolve different Electron versions and transitive dependency graphs. The launcher automatically invokes `npm install` when `node_modules` is absent. npm installation can download packages from the configured registry and execute package lifecycle scripts with the privileges of the invoking user. The subsequent `npx electron .` command executes the installed Electron package. No malicious dependency is present in the reviewed source, and Electron is a legitimate package. The weakness is that installation is not deterministic and depends on the integrity of the registry, npm configuration, package publisher account, and dependency versions available at installation time. ### Attack Path 1. A user invokes `scripts/launch.sh` on a system where `node_modules` does not exist, or manually follows the documented `npm install` instructions. 2. npm resolves `electron` and its transitive dependencies without a reviewed lockfile. 3. An attacker compromises the configured npm registry, a relevant publisher account, the local npm registry configuration, or a future dependency release accepted by the version range. 4. npm downloads the attacker-controlled package content. 5. Malicious lifecycle code can execute during installation, or malicious runtim ...[truncated 586 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin Electron to a reviewed exact version rather than a mutable range: ```json "devDependencies": { "electron": "34.0.0" } ``` 2. Generate, review, and commit `package-lock.json`. 3. Replace automatic `npm install` with deterministic installation: ```bash npm ci ``` 4. Configure npm to use an explicitly trusted registry and enforce HTTPS. 5. Review dependency changes and lockfile diffs before upgrading. 6. Use automated dependency vulnerability and integrity scanning in CI. 7. Where compatible with the installation process, consider disabling package lifecycle scripts: ```bash npm ci --ignore-scripts ``` 8. Avoid using `npx` where resolution could be ambiguous. Invoke the installed, locked binary through an npm script or an explicit local path. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
app/main.js:67
Finding
Overbroad Automatic Media Permission Grants in System Audio Mode<![CDATA[ ## Vulnerability Details **File Location**: `app/main.js:67-77`, `app/preload.js:15-18`, `app/lobster.html:220-226` **Vulnerability Type**: Excessive media permissions and insufficient request-origin validation **Risk Level**: Medium ### Vulnerable Code `app/main.js:67-77`: ```javascript if (AUDIO_MODE === 'system') { const MEDIA_PERMISSIONS = ['media', 'display-capture', 'audioCapture', 'videoCapture']; session.defaultSession.setPermissionRequestHandler((webContents, permission, callback) => { callback(MEDIA_PERMISSIONS.includes(permission)); }); session.defaultSession.setDisplayMediaRequestHandler((request, callback) => { desktopCapturer.getSources({ types: ['screen'] }).then((sources) => { callback({ video: sources[0], audio: 'loopback' }); }); }); } ``` `app/preload.js:15-18`: ```javascript getSources: () => require('electron').desktopCapturer.getSources({ types: ['screen'], thumbnailSize: { width: 0, height: 0 }, }), ``` `app/lobster.html:220-226`: ```javascript const stream = await navigator.mediaDevices.getDisplayMedia({ video: { width: 1, height: 1, frameRate: 1 }, audio: { echoCancellation: false, noiseSuppression: false, autoGainControl: false } }); stream.getVideoTracks().forEach(tr => tr.stop()); audioCtx = new (window.AudioContext || window.webkitAudioContext)(); if (audioCtx.state === 'suspended') await audioCtx.resume(); ``` ### Technical Analysis The declared purpose of system mode is to capture system loopback audio. However, the permission handler automatically approves the following broad permission classes: - Generic media access - Display capture - Audio capture - Video capture The handler does not validate: - The requesting `webContents` - The requesting frame - The requesting URL or origin - Whether the request came from the bundled local page - Whether camera or microphone access is actually required The display-media handler similarly returns the first available screen source w ...[truncated 2357 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove camera, microphone, and generic media permission classes unless they are strictly required. Grant only the minimum permission necessary for loopback display capture. 2. Validate the requesting `webContents` and frame URL before granting a permission: ```javascript session.defaultSession.setPermissionRequestHandler( (webContents, permission, callback, details) => { const expectedURL = win?.webContents.getURL(); const trustedRequester = webContents === win?.webContents && details.requestingUrl === expectedURL; callback(trustedRequester && permission === 'display-capture'); } ); ``` 3. Apply equivalent origin and frame validation in `setDisplayMediaRequestHandler`. 4. Reject a capture request when no valid screen source exists and add explicit error handling. 5. Remove the unused `getSources` function from `preload.js` so renderer code cannot enumerate screen sources through the bridge. 6. Keep the preload API minimal and validate all arguments crossing IPC or context-bridge boundaries. 7. Consider using a dedicated Electron session partition instead of `session.defaultSession` to isolate permission state. 8. Define an explicit restrictive Content Security Policy for `lobster.html`. 9. Prevent untrusted navigation and unexpected window creation: ```javascript win.webContents.on('will-navigate', event => event.preventDefault()); win.webContents.setWindowOpenHandler(() => ({ action: 'deny' })); ``` 10. Preserve `nodeIntegration: false` and `contextIsolation: true`, and explicitly enable renderer sandboxing where compatible. ]]>
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (10)

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The install instructions tell users to `npm install` in a bundled app directory and then launch the Electron app, but they do not clearly warn that this will fetch third-party packages and execute local application code on the user's machine. Because the skill explicitly bundles an Electron application, the context makes the omission more significant: Electron apps have broad local-system access and npm install may run lifecycle scripts.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding
Using `npx electron .` without pinning a version allows resolution of whatever Electron package/version is available at execution time, which can change across environments or over time. In a skill that launches a bundled desktop app, this increases supply-chain and reproducibility risk because users may execute unexpected code or a newer package with different security behavior.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The helper script is presented as a convenience command but omits a prominent warning that it automatically performs first-run package installation and then executes the application. This can surprise users into both installing dependencies and running code in one step, which is riskier in the context of a bundled Electron desktop overlay than in purely informational documentation.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The HTML advertises two audio modes, including a 'system' mode that captures loopback audio and reacts to everything played on the host, not just TTS output. That is broader behavior than the skill description implies, creating an unnecessary privacy-sensitive capability and a mismatch between stated purpose and actual access.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The code requests display-media with audio to obtain system loopback audio, which is a powerful capture mechanism unrelated to the minimum needed for a desktop avatar that lip-syncs to a known TTS source. Even if the current code only computes animation metrics locally, granting this permission exposes broader host audio than users would reasonably expect.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
System audio capture is attempted automatically at startup, and the only notice is a console message after failure rather than a clear in-app warning before requesting access. In an Electron-based desktop overlay context, this makes the capability more dangerous because users may not understand they are authorizing monitoring of all system playback rather than just TTS lip-sync input.

Rp1

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding
Using `npx electron .` without pinning a specific package/version allows `npx` to resolve and execute whatever `electron` package is available from the environment or registry at runtime. If Electron is not already installed locally, this can result in downloading and running an unexpected or compromised package, which is especially risky here because the skill launches a desktop app and performs `npm install` in the same directory.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"author": "JoeProAI",
  "license": "MIT",
  "devDependencies": {
    "electron": "^34.0.0"
  }
}
Confidence
95% confidence
Finding
The Electron dependency is specified with a caret range (^34.0.0), which permits installation of newer minor and patch releases and makes builds non-reproducible. In a desktop app framework like Electron, this increases supply-chain and patch-management risk because different installs may resolve to different code, complicating verification and exposure assessment.

Unverifiable Dependency: electron has 16 known advisory(ies) (CVE-2020-15174 (Unpreventable top-level navigation); CVE-2026-34776 (Electron: Out-of-bounds read in second-instance IPC on macOS and Linux); CVE-2022-21718 (Renderers can obtain access to random bluetooth device without permission in Ele) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
87% confidence
Finding
Electron has a history of security advisories, and because the manifest uses a non-exact version, it is not possible to verify from this file alone which patched or vulnerable release will actually be installed. This uncertainty is more significant in this skill's context because it distributes and launches a bundled Electron desktop app, where framework vulnerabilities can directly affect the user's local system.

Missing User Warnings

Low
Confidence
77% confidence
Finding
The preload bridge exposes desktop source enumeration via desktopCapturer.getSources, which can reveal information about the user's displays and is tied to system audio capture. In this file there is no confirmation prompt, user-facing log, or explicit warning comment/docstring explaining that renderer code can invoke this capability.

Static analysis

Detected: suspicious.install_untrusted_source

Install source points to URL shortener or raw IP.

Warn
Code
suspicious.install_untrusted_source
Location
app/config.json:6