Back to skill

Security audit

Clawprompt

Security checks for vulnerabilities and agentic risk

Overview

This teleprompter does what it claims, but its LAN remote-control server lets unauthenticated network clients read, replace, and control scripts, so users should review it carefully before installing.

Install only if you are comfortable running a LAN-accessible teleprompter server. Use it on a trusted private network, avoid confidential scripts, stop the server when finished, and prefer a version that adds a pairing token, authentication, origin checks, payload limits, local-only QR generation, and a committed lockfile.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/server.js:86
Finding

Unauthenticated LAN Clients Can Read, Replace, and Control Teleprompter Sessions

Content
View full analysis
{ clients.set(ws, { role: 'main' }); // default role ws.send(JSON.stringify({ type: 'state', ...state })); ws.on('message', (raw) => { try { const msg = JSON.parse(raw); if (msg.type === 'register') { clients.set(ws, { role: msg.role || 'main' }); broadcastRemoteCount(); } else if (msg.type === 'sync') { // Main teleprompter syncs state state = { idx: msg.idx, total: msg.total, current: msg.current || '', next: msg.next || '' }; broadcast({ type: 'state', ...state }, ws); } else if (msg.type === 'cmd') { // Remote sends command → broadcast to all (main will handle) broadcast({ type: 'cmd', action: msg.action }, ws); } else if (msg.type === 'text') { // Remote uploaded text → broadcast to all broadcast({ type: 'text', text: msg.text }, ws); } else if (msg.type === 'fulltext') { // Main syncs text to remotes broadcast({ type: 'fulltext', text: msg.text }, ws); } } catch {} }); ``` The network exposure is established at `scripts/server.js`, lines 117–124: ```js server.listen(PORT, '0.0.0.0', () => { console.log(`\n🎬 ClawPrompt Server`); console.log(` 电脑提词器: http://localhost:${PORT}`); console.log(` 手机遥控: http://${lanIP}:${PORT}/remote`); console.log(` (确保手机和电脑在同一 WiFi)\n`); }); ``` ### Technical Analysis The server listens on every network interface and accepts all WebSocket connections without credentials or a cryptographically random pairing token. The QR code only communicates the service URL; scanning it does not establish a trusted pairing relationship. A newly connected client immediately receives the current shared ...[truncated 1782 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/server.js:38
Finding

Unbounded QR Generation and WebSocket Messages Permit Resource Exhaustion

Content
View full analysis
{ if (err) { res.writeHead(500); res.end(); return; } res.writeHead(200, { 'Content-Type': 'image/png', 'Cache-Control': 'max-age=3600' }); res.end(buf); }); ``` WebSocket input is parsed, retained, and rebroadcast without schema or length validation at lines 91–111: ```js ws.on('message', (raw) => { try { const msg = JSON.parse(raw); if (msg.type === 'register') { clients.set(ws, { role: msg.role || 'main' }); broadcastRemoteCount(); } else if (msg.type === 'sync') { // Main teleprompter syncs state state = { idx: msg.idx, total: msg.total, current: msg.current || '', next: msg.next || '' }; broadcast({ type: 'state', ...state }, ws); } else if (msg.type === 'cmd') { // Remote sends command → broadcast to all (main will handle) broadcast({ type: 'cmd', action: msg.action }, ws); } else if (msg.type === 'text') { // Remote uploaded text → broadcast to all broadcast({ type: 'text', text: msg.text }, ws); } else if (msg.type === 'fulltext') { // Main syncs text to remotes broadcast({ type: 'fulltext', text: msg.text }, ws); } } catch {} }); ``` ### Technical Analysis The `size` query parameter is parsed and passed directly to the QR encoder. No finite-number check or minimum/maximum bound is applied. A sufficiently large width can cause expensive image allocation and encoding. WebSocket mes ...[truncated 1684 chars]
Remediation
View remediation

other

Note
Location
scripts/index.html:143
Finding

External QR Fallback Discloses the Private Service Address

Content
View full analysis
{ // Fallback: use current host const url = `${location.protocol}//${location.host}/remote`; $('qrUrl').textContent = url; $('qrImg').src = `https://api.qrserver.com/v1/create-qr-code/?size=160x160&data=${encodeURIComponent(url)}`; $('tpQr').src = `https://api.qrserver.com/v1/create-qr-code/?size=100x100&data=${encodeURIComponent(url)}`; }); ``` ### Technical Analysis If the local `/qr-url` request fails, the browser constructs the private remote-control URL and includes it in requests to `api.qrserver.com`. This reveals the local host or IP address, port, remote endpoint path, requester IP address, and usage timing to a third-party provider. The project already has server-side QR generation through the local `qrcode` dependency, so the external fallback is not required for normal operation. The fallback and its associated metadata disclosure are not documented in the user-facing Skill instructions. No script body is transmitted through this specific path; the disclosure is limited to service and request metadata. ### Attack Path 1. The browser fails to retrieve or parse `/qr-url`. 2. The fallback handler constructs a URL such as `http://192.168.1.20:7870/remote`. 3. The browser requests an image from the external QR provider with that private URL encoded in the query string. 4. The provider receives and can log the internal address, port, path, public requester address, browser metadata, and request time. 5. Two requests may be generated because both QR image elements use the external provider. ### Impact Assessment The external provider obtains limited network-topology and usage metadata without explicit user consent. This may reveal: - The private address and port used by the local service. - The ...[truncated 272 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
SKILL.md:32
Finding

Dependency Installation Is Not Reproducible or Cryptographically Locked

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (13)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger list includes broad, common phrases such as 'teleprompter', '提词', and 'I need a prompter', which can cause the skill to activate when the user is speaking generally rather than explicitly requesting this specific tool. Unintended invocation can redirect users into running a local server or opening a workflow they did not intend, increasing the chance of confusion, accidental execution, or misuse of adjacent capabilities.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

When local QR generation fails, the code sends the remote-control URL to api.qrserver.com, a third-party service, without notifying the user. Even though the transmitted value is a URL rather than the script itself, it leaks session/network metadata to an external party and introduces an undeclared dependency that may be inappropriate in privacy-sensitive environments.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
96% confidence
Finding

This line transmits the remote-control URL to an external QR code generation service. That external transmission is unnecessary for core functionality and can expose internal hostnames, session endpoints, or usage metadata to a third party without user awareness.

Content

Scanner excerpt · scripts/index.html (reported line 121)May include surrounding context.

html
// Fallback: use current host
    const url = `${location.protocol}//${location.host}/remote`;
    $('qrUrl').textContent = url;
    $('qrImg').src = `https://api.qrserver.com/v1/create-qr-code/?size=160x160&data=${encodeURIComponent(url)}`;
    $('tpQr').src = `https://api.qrserver.com/v1/create-qr-code/?size=100x100&data=${encodeURIComponent(url)}`;
  });
}

External Transmission

Medium
Category
Data Exfiltration
Confidence
96% confidence
Finding

This second QR image request repeats the same third-party data disclosure for the teleprompter view, expanding external exposure each time the fallback path is used. In some deployments, the leaked URL could reveal internal addressing or operational details about the remote-control endpoint.

Content

Scanner excerpt · scripts/index.html (reported line 122)May include surrounding context.

html
const url = `${location.protocol}//${location.host}/remote`;
    $('qrUrl').textContent = url;
    $('qrImg').src = `https://api.qrserver.com/v1/create-qr-code/?size=160x160&data=${encodeURIComponent(url)}`;
    $('tpQr').src = `https://api.qrserver.com/v1/create-qr-code/?size=100x100&data=${encodeURIComponent(url)}`;
  });
}

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The page automatically synchronizes the full script and current prompt state over WebSocket to connected devices, but the UI does not clearly warn users that their entered text will be transmitted across the network. Because teleprompter scripts may contain unreleased content, personal data, or confidential talking points, this creates a privacy and data-exposure risk, especially if users assume the text stays local.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The console output includes Chinese-only user-facing text, which forces a specific language for operators of the skill. There is no indication that the skill is region-specific or that users can opt into another language, so this appears to violate the language/locale policy.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
71% confidence
Finding

The manifest-like description hard-codes trigger phrases in multiple languages, but it does not explain whether activation depends on the user's preferred language or locale. This can violate language/locale policy expectations if the skill matches or responds based on a language the user did not opt into.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The document language is set to zh-CN and the visible interface text is presented in Chinese only. There is no indication that this is a region-specific tool or that users can opt into another language, which may violate language/locale choice policy.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency uses a caret range (^1.5.4), which allows installation of newer compatible releases rather than a single reviewed version. This creates supply-chain uncertainty because different environments may resolve to different package contents, making builds less reproducible and potentially introducing vulnerable or malicious updates without code changes.

Content

Scanner excerpt · scripts/package.json (reported line 14)May include surrounding context.

json
"author": "",
  "license": "ISC",
  "dependencies": {
    "qrcode": "^1.5.4",
    "ws": "^8.19.0"
  }
}

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

The ws dependency is specified with a caret range (^8.19.0), so the installed version may vary across environments and over time. Because ws is a network-facing WebSocket library in a teleprompter app with mobile pairing/remote control, version drift increases the risk of pulling in a release with exploitable bugs or inconsistent security behavior.

Content

Scanner excerpt · scripts/package.json (reported line 15)May include surrounding context.

json
"license": "ISC",
  "dependencies": {
    "qrcode": "^1.5.4",
    "ws": "^8.19.0"
  }
}

Unverifiable Dependency: ws has 7 known advisory(ies) (CVE-2016-10518 (Remote Memory Disclosure in ws); CVE-2024-37890 (ws affected by a DoS when handling a request with many HTTP headers); CVE-2026-45736 (ws: Uninitialized memory disclosure) +4 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
91% confidence
Finding

The manifest includes ws, which has multiple known advisories, but the dependency is not pinned, so it is impossible to verify from this file whether the actually installed version is affected. In this skill's context, ws is likely central to phone pairing and remote control features, so a vulnerable WebSocket package could expose the service to denial of service or information disclosure over the network.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The document declares zh-CN and all visible UI strings are in Simplified Chinese, with no indication that users can opt into another language. This is a natural-language locale policy concern because the skill effectively forces a specific language without user choice or justification in the file.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.