Back to skill

Security audit

Avatar

Security checks for vulnerabilities and agentic risk

Overview

This avatar skill is mostly coherent, but it exposes powerful agent, messaging, and provider-key capabilities with weak access controls.

Review before installing. Run it only on a trusted local machine, bind the server to localhost, add authentication before exposing any port, avoid enabling Slack/email or Stream Deck sends until confirmations and recipient limits exist, rotate any Simli key exposed during testing, and update/pin dependencies.

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 (6)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
src/server.ts:286
Finding
Unauthenticated privileged API endpoints are exposed on all network interfaces<![CDATA[ ## Vulnerability Details **File Location**: `src/server.ts:286-460`, `src/server.ts:650` **Vulnerability Type**: Missing authentication and authorization; excessive network exposure **Risk Level**: High ### Vulnerable Code ```ts const app = express(); app.use(express.json()); // Client config endpoint app.get('/api/client-config', (_req: Request, res: Response) => { const clientConfig: ClientConfig = getClientConfig(config); res.json(clientConfig); }); app.post('/api/speaking-done', async (_req: Request, res: Response) => { await setSpeaking(false); res.json({ ok: true }); }); app.post('/api/chat', async (req: Request, res: Response) => { const { message, lang } = req.body; // ... const response = await sendChat(augmented); // ... res.json({ spoken, detail }); }); app.post('/api/send-slack', async (req: Request, res: Response) => { const { text } = req.body; // ... const response = await sendChat( `[SYSTEM] Send the following message via Slack DM to targets: ${targetStr}. Do NOT modify the content, just send it as-is. Reply with just "Sent!" after.\n\n${text}` ); res.json({ ok: true, response }); }); app.post('/api/tts', async (req: Request, res: Response) => { const { text, lang, voiceId: customVoiceId } = req.body; // ... const ttsRes = await fetch( `https://api.elevenlabs.io/v1/text-to-speech/${voiceId}?output_format=pcm_16000`, { method: 'POST', headers: { 'xi-api-key': config.secrets.elevenLabsApiKey, 'Content-Type': 'application/json', }, body: JSON.stringify(ttsBody), } ); // ... }); app.post('/api/send-email', async (req: Request, res: Response) => { const { text } = req.body; // ... const response = await sendChat( `[SYSTEM] Send the following content to ${config.integrations.email.recipient} as an email from ${config.app.name}. Use a suitable subject line based on the content. Do NOT modify the content. Reply with just "Sent!" after ...[truncated 2322 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Bind the server explicitly to loopback by default: ```ts app.listen(PORT, '127.0.0.1', callback); ``` 2. Require authenticated sessions for all `/api/*` routes. 3. Apply per-action authorization, especially to Slack, email, agent, and TTS endpoints. 4. Add CSRF protection and validate `Origin` or `Referer` for browser-originated state-changing requests. 5. Require explicit user confirmation immediately before sending Slack or email messages. 6. Add rate limiting, request quotas, and audit logging. 7. Configure a conservative JSON body-size limit, for example: ```ts app.use(express.json({ limit: '32kb' })); ``` 8. If remote access is required, place the service behind TLS and an authenticated reverse proxy rather than exposing Express directly. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/config/index.ts:112
Finding
Simli API key is disclosed through an unauthenticated client configuration endpoint<![CDATA[ ## Vulnerability Details **File Location**: `src/config/index.ts:112-124`, `src/server.ts:316-320` **Vulnerability Type**: Client-side exposure of a provider credential **Risk Level**: High ### Vulnerable Code ```ts /** * Get configuration safe to send to the client (no secrets) */ export function getClientConfig(config: Config): ClientConfig { return { app: config.app, avatars: config.avatars, languages: config.languages, fillers: config.fillers, simliApiKey: config.secrets.simliApiKey, }; } ``` ```ts // Client config endpoint - safe to expose (no secrets except simli key) app.get('/api/client-config', (_req: Request, res: Response) => { const clientConfig: ClientConfig = getClientConfig(config); res.json(clientConfig); }); ``` ### Technical Analysis The application explicitly copies `SIMLI_API_KEY` from the server's secret configuration into a JSON response available from `/api/client-config`. The endpoint is unauthenticated. The comment claiming that the response contains no secrets is contradicted by the implementation. A long-lived provider API key is a bearer credential; anyone who obtains it may attempt to use it independently of this application. This exposure is amplified because the Express service is not explicitly restricted to the loopback interface. ### Attack Path 1. An attacker gains network access to the avatar server. 2. The attacker sends `GET /api/client-config`. 3. The server returns JSON containing `simliApiKey`. 4. The attacker extracts the key. 5. The attacker reuses the credential with Simli services outside the avatar application, subject to the key's provider-side privileges. A browser XSS payload executing in the application origin could perform the same extraction. ### Impact Assessment Potential impact includes: - Unauthorized Simli sessions. - Consumption of the victim's service quota. - Financial loss or account throttling. - Exposure of provider resources accessible to the API ...[truncated 64 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not return long-lived API keys from generic configuration endpoints. 2. If Simli supports ephemeral browser tokens, mint short-lived, narrowly scoped session credentials on the server. 3. Authenticate the token-minting endpoint and apply rate and quota controls. 4. Restrict the HTTP server to `127.0.0.1` unless remote access is explicitly configured. 5. Rotate the currently configured Simli key after correcting the exposure. 6. Rename and restructure `ClientConfig` so secret values cannot be added accidentally. 7. Add automated tests asserting that `/api/client-config` never contains keys, tokens, or other secret fields. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/client/app.ts:220
Finding
Unsanitized agent Markdown and configuration values allow DOM-based cross-site scripting<![CDATA[ ## Vulnerability Details **File Location**: `src/client/app.ts:220-225`, `src/client/app.ts:490-515`, `index.html:541` **Vulnerability Type**: DOM-based cross-site scripting **Risk Level**: High ### Vulnerable Code ```ts if (detail) { detailContentEl.innerHTML = window.marked.parse(detail); sendSlackBtn.style.display = 'flex'; sendSlackBtn.dataset.text = detail; } else { sendSlackBtn.style.display = 'none'; } ``` ```ts for (const lang of clientConfig.languages) { const btn = document.createElement('button'); btn.className = 'avatar-option'; btn.dataset.lang = lang.code; const flag = lang.flag ? getFlagEmoji(lang.flag) : ''; btn.innerHTML = `<div class="avatar-label">${flag} ${lang.name}</div>`; langOptions.appendChild(btn); } ``` ```ts for (const avatar of clientConfig.avatars) { const btn = document.createElement('button'); btn.className = 'avatar-option'; btn.dataset.faceId = avatar.faceId; btn.dataset.voiceId = avatar.voiceId; btn.innerHTML = `<div class="avatar-label">${avatar.name}</div>`; avatarOptions.appendChild(btn); } ``` ```html <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> ``` ### Technical Analysis The client converts agent-controlled `detail` output to HTML through Marked and assigns the result directly to `innerHTML`. Marked is a Markdown parser, not an HTML sanitizer. No sanitization layer is applied before insertion into the DOM. The application also inserts `lang.name` and `avatar.name` from `avatar.config.json` into `innerHTML`. These values are locally configurable and could become attacker-controlled if configuration is modified or generated by another system. No restrictive Content Security Policy is shown in the audited HTML. Therefore, active HTML generated from malicious Markdown or configuration can potentially execute scripts or event handlers in the application's origin. ### Attack Path Agent-output path: 1. An attacker causes the OpenClaw agent to ret ...[truncated 1193 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Sanitize all generated Markdown HTML with a maintained allowlist sanitizer such as DOMPurify: ```ts const parsed = window.marked.parse(detail); detailContentEl.innerHTML = DOMPurify.sanitize(parsed); ``` 2. Disable raw HTML in Markdown if the parser supports that mode. 3. Use `textContent` and DOM construction for configuration labels: ```ts const label = document.createElement('div'); label.className = 'avatar-label'; label.textContent = `${flag} ${lang.name}`; btn.appendChild(label); ``` 4. Apply the same safe construction to avatar names. 5. Add a restrictive Content Security Policy that disallows inline script and event-handler execution. 6. Validate and constrain all configuration strings at load time. 7. Add tests using payloads involving event handlers, SVG, malformed tags, and dangerous URL schemes. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/server.ts:32
Finding
Persistent device private key is stored as plaintext Base64 without explicit restrictive permissions<![CDATA[ ## Vulnerability Details **File Location**: `src/server.ts:32-57` **Vulnerability Type**: Insecure storage of authentication key material **Risk Level**: Medium ### Vulnerable Code ```ts function loadOrCreateKeypair(): void { if (existsSync(KEYPAIR_PATH)) { const data = JSON.parse(readFileSync(KEYPAIR_PATH, 'utf8')); privateKey = crypto.createPrivateKey({ key: Buffer.from(data.privateDer, 'base64'), format: 'der', type: 'pkcs8', }); publicKeyRaw = Buffer.from(data.publicRaw, 'base64'); publicKeyBase64url = toBase64url(publicKeyRaw); } else { const pair = crypto.generateKeyPairSync('ed25519'); privateKey = pair.privateKey; const spki = pair.publicKey.export({ format: 'der', type: 'spki' }); publicKeyRaw = spki.subarray(spki.length - 32); publicKeyBase64url = toBase64url(publicKeyRaw); const privDer = pair.privateKey.export({ format: 'der', type: 'pkcs8' }); writeFileSync( KEYPAIR_PATH, JSON.stringify({ privateDer: privDer.toString('base64'), publicRaw: publicKeyRaw.toString('base64'), }) ); } } ``` ### Technical Analysis The application exports the Ed25519 private key in PKCS#8 DER form, Base64-encodes it, and writes it to `./device-key.json`. Base64 provides no confidentiality. The write operation does not explicitly request owner-only permissions, and the path is relative to the current working directory rather than a protected application-data directory. Actual permissions depend on the process umask and surrounding directory permissions. This behavior explains the static scanner's decode pattern: the code decodes key material and supplies it to `crypto.createPrivateKey`; it does not decode and execute a software payload. ### Attack Path 1. Another local user, compromised process, backup service, or accidental artifact publication obtains `device-key.json`. 2. The attacker Base64-decodes `privateDer`. 3. The attacker reconstructs th ...[truncated 637 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Store the private key in an operating-system credential store or keychain where available. 2. Otherwise, use a dedicated per-user application-data directory with owner-only permissions. 3. Create the file atomically with mode `0600`, for example: ```ts writeFileSync(keyPath, serializedKey, { mode: 0o600, flag: 'wx', }); ``` 4. Verify and correct permissions when loading an existing key. 5. Avoid placing the key in the project or current working directory. 6. Add `device-key.json` to ignore and packaging exclusion rules. 7. Document key rotation and device revocation procedures. ]]>

T08 · Insecure Dependencies

Warning
Location
package.json:47
Finding
Mutable runtime dependency and unverified CDN script create supply-chain risk<![CDATA[ ## Vulnerability Details **File Location**: `package.json:47`, `index.html:541` **Vulnerability Type**: Unpinned and remotely mutable third-party code **Risk Level**: Medium ### Vulnerable Code ```json "dependencies": { "dotenv": "^16.4.0", "express": "^5.2.1", "simli-client": "latest", "ws": "^8.19.0" } ``` ```html <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> ``` ### Technical Analysis The runtime dependency `simli-client` uses the mutable `latest` tag rather than an explicit version. Although the current lockfile records a resolved package, installations that regenerate or ignore the lockfile may retrieve a different release without source review. The browser also loads Marked from a CDN without an exact version or a Subresource Integrity hash. This allows the effective browser-side code to change independently of the audited repository. These patterns do not prove that the present dependencies are malicious. They create unnecessary exposure to compromised upstream releases, CDN compromise, package-account takeover, and unexpected breaking changes. ### Attack Path NPM path: 1. A deployment performs dependency installation without strictly enforcing the committed lockfile. 2. The `latest` tag resolves to a newer or compromised `simli-client` release. 3. The application bundles or executes the changed package. 4. Malicious package code runs in the application's trusted context. CDN path: 1. The CDN asset or upstream package is modified or compromised. 2. A user loads the avatar page. 3. The browser downloads the changed script without integrity verification. 4. The script executes in the avatar origin and can invoke same-origin APIs. ### Impact Assessment A compromised dependency may obtain: - Browser-origin access to avatar APIs and exposed client configuration. - Access to user interactions and rendered agent content. - The ability to issue Slack, email, TTS, or chat requests. - Server-side privileg ...[truncated 170 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin `simli-client` to an explicitly reviewed version. 2. Use `npm ci` in CI and production so the committed lockfile is enforced. 3. Enable automated dependency review and vulnerability scanning. 4. Bundle Marked locally through the package manager rather than loading it at runtime from a CDN. 5. If a CDN is retained, use an exact versioned URL and a verified Subresource Integrity hash with `crossorigin="anonymous"`. 6. Adopt a restrictive Content Security Policy that limits script sources. 7. Review dependency install scripts, especially native optional dependencies, before production deployment. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/server.ts:102
Finding
Arbitrary gateway configuration can disclose the OpenClaw token and requests broad operator scopes<![CDATA[ ## Vulnerability Details **File Location**: `src/server.ts:102-150`, `src/config/schema.ts:91-143` **Vulnerability Type**: Insufficient destination validation and excessive gateway authorization scope **Risk Level**: High ### Vulnerable Code ```ts gwWs = new WebSocket(GW_URL, { headers: { origin: `http://localhost:${PORT}` }, }); ``` ```ts const token = config.secrets.openclawToken || ''; const id = msgId++; gwWs!.send( JSON.stringify({ type: 'req', id: String(id), method: 'connect', params: { minProtocol: 3, maxProtocol: 3, client: { id: 'webchat', version: '1.0.0', platform: 'macos', mode: 'webchat', }, role: 'operator', scopes: ['operator.read', 'operator.write'], caps: [], commands: [], permissions: {}, auth: { token }, locale: 'en-US', userAgent: `${config.app.name}/1.0`, device: { id: deviceId, publicKey: publicKeyBase64url, signature: signature, signedAt: now, nonce: challengeNonce, }, }, }) ); ``` The configuration validator checks required keys and avatar/language fields but does not validate `config.openclaw.gatewayUrl`: ```ts export function validateConfig(config: Config): void { const errors: string[] = []; if (!config.secrets.simliApiKey) { errors.push('SIMLI_API_KEY environment variable is required'); } if (!config.secrets.elevenLabsApiKey) { errors.push('ELEVENLABS_API_KEY environment variable is required'); } // Avatar and language validation only. // No gateway URL scheme, host, or trust validation. } ``` ### Technical Analysis The gateway URL is configurable and passed directly to the WebSocket constructor. The validator does not restrict its host or scheme and does not require `wss://` for remote endpoints. After receiving a challenge from that endpoint, the server transmits the configured OpenClaw token and requests both ...[truncated 1605 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Permit loopback gateway addresses by default and reject non-loopback destinations unless remote access is explicitly enabled. 2. Require `wss://` for every non-loopback gateway. 3. Validate gateway hosts against an explicit administrator-controlled allowlist. 4. Display a clear warning before sending credentials to a newly configured gateway. 5. Request only the minimum gateway scopes needed for avatar chat. 6. Separate read-only chat access from integrations that require write privileges. 7. Use short-lived, audience-bound tokens where the gateway supports them. 8. Do not include reusable tokens in signed payload material unless required by a documented protocol. 9. Add certificate and hostname verification tests for remote gateway configurations. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (71)

Known Vulnerable Dependency: tar==7.5.7 — 9 advisory(ies): CVE-2026-59873 (node-tar: Decompression/parse DoS via unlimited input); CVE-2026-26960 (Arbitrary File Read/Write via Hardlink Target Escape Through Symlink Chain in no); CVE-2026-59874 (node-tar: Negative tar entry size causes infinite loop in archive replace) +6 more

Critical
Category
Supply Chain
Confidence
90% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Credential Access

High
Category
Privilege Escalation
Content
2. **Configure environment**
   ```bash
   cp .env.example .env
   # Edit .env and add your API keys
   ```
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
2. **Configure environment**
   ```bash
   cp .env.example .env
   # Edit .env and add your API keys
   ```

3. **Start the server**
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
2. **Configure environment**
   ```bash
   cp .env.example .env
   # Edit .env and add your API keys
   ```

3. **Start the server**
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
Hardware integration and shortcut actions that can trigger send_slack or send_email go well beyond passive avatar rendering. In this context, concealed action shortcuts are especially risky because they can turn a presentation interface into an action-taking control surface capable of transmitting sensitive content or triggering workflows.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
Hardware integration and shortcut actions that can trigger send_slack or send_email go well beyond passive avatar rendering. In this context, concealed action shortcuts are especially risky because they can turn a presentation interface into an action-taking control surface capable of transmitting sensitive content or triggering workflows.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
Hardware integration and shortcut actions that can trigger send_slack or send_email go well beyond passive avatar rendering. In this context, concealed action shortcuts are especially risky because they can turn a presentation interface into an action-taking control surface capable of transmitting sensitive content or triggering workflows.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
Hardware integration and shortcut actions that can trigger send_slack or send_email go well beyond passive avatar rendering. In this context, concealed action shortcuts are especially risky because they can turn a presentation interface into an action-taking control surface capable of transmitting sensitive content or triggering workflows.

Hidden Instructions

High
Category
Prompt Injection
Content
<div id="top-bar">
    </div>

    <!-- Settings Page -->
    <div id="settings-page">
      <div class="settings-header">
        <h2>Settings</h2>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Known Vulnerable Dependency: nanoid==3.3.11 — 3 advisory(ies): CVE-2026-67214 (nanoid: non-secure generators can loop indefinitely with negative size); CVE-2026-67213 (nanoid: custom generators can loop indefinitely when size is zero); CVE-2026-73086 (nanoid: Integer Overflow or Wraparound)

High
Category
Supply Chain
Confidence
80% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Known Vulnerable Dependency: path-to-regexp==8.3.0 — 2 advisory(ies): CVE-2026-4923 (path-to-regexp vulnerable to Regular Expression Denial of Service via multiple w); CVE-2026-4926 (path-to-regexp vulnerable to Denial of Service via sequential optional groups)

High
Category
Supply Chain
Confidence
92% confidence
Finding
path-to-regexp 8.3.0 is a transitive runtime dependency of Express router and the cited issues are ReDoS/DoS conditions in route matching. Because this skill depends on Express at runtime, maliciously crafted request paths may trigger excessive CPU consumption and degrade or deny service availability.

Known Vulnerable Dependency: postcss==8.5.6 — 4 advisory(ies): CVE-2026-45623 (PostCSS: Arbitrary file read and information disclosure via attacker-controlled ); CVE-2026-69153 (PostCSS: incomplete fix of GHSA-6g55-p6wh-862q — attacker-controlled sourceMappi); CVE-2026-41305 (PostCSS has XSS via Unescaped </style> in its CSS Stringify Output) +1 more

High
Category
Supply Chain
Confidence
80% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Known Vulnerable Dependency: rollup==4.57.1 — 1 advisory(ies): CVE-2026-27606 (Rollup 4 has Arbitrary File Write via Path Traversal)

High
Category
Supply Chain
Confidence
80% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Known Vulnerable Dependency: vite==5.4.21 — 3 advisory(ies): CVE-2026-39365 (Vite Vulnerable to Path Traversal in Optimized Deps `.map` Handling); CVE-2026-53571 (vite: `server.fs.deny` bypass on Windows alternate paths); CVE-2026-53632 (launch-editor: NTLMv2 hash disclosure via UNC path handling on Windows)

High
Category
Supply Chain
Confidence
80% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Known Vulnerable Dependency: ws==8.19.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
93% confidence
Finding
ws 8.19.0 is a direct runtime dependency, and the cited issues include memory disclosure and memory exhaustion from attacker-controlled WebSocket traffic. Given this skill's interactive avatar/video use case, WebSockets are especially likely to be exposed to remote clients, which makes the availability and data exposure risk materially more relevant.

Credential Access

High
Category
Privilege Escalation
Content
} catch (err) {
    console.error('Configuration error:', (err as Error).message);
    console.error('\nMake sure you have:');
    console.error('  1. Copied .env.example to .env');
    console.error('  2. Added your SIMLI_API_KEY and ELEVENLABS_API_KEY');
    process.exit(1);
  }
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Missing User Warnings

High
Confidence
98% confidence
Finding
Email sending is triggered from Stream Deck events with no user-facing confirmation, preview, or local interaction at the time of transmission. Because the action can be initiated remotely through the event channel, it creates a higher-risk path for accidental or unauthorized outbound sharing of potentially sensitive AI-generated content.

Intent-Code Divergence

High
Confidence
98% confidence
Finding
The function comment explicitly says the returned client config contains no secrets, but `getClientConfig()` includes `config.secrets.simliApiKey`. Sending an API key to the client exposes a credential to any user or script with access to the frontend bundle or network responses, enabling unauthorized use of the Simli service and possible billing abuse or account compromise.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The chat prompt tells the agent it has full access to HubSpot, Gmail, Calendar, Notion, and Slack, despite the avatar skill's narrow stated purpose. Embedding user input into a prompt with broad tool authority creates an overprivileged agent path where ordinary conversation can steer high-impact actions or data access.

Ssd 1

High
Confidence
99% confidence
Finding
User input is concatenated into a privileged natural-language instruction that grants broad workspace access and asks the model to use tools. This creates a prompt-layer capability escalation path where crafted conversation can steer the agent into sensitive retrievals or side effects not enforced by code-level policy.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
This server exposes Slack DM and email sending capabilities even though the skill is described as an avatar/TTS renderer. That mismatch materially expands the trust boundary: a user or downstream agent can trigger outbound communications and potential data disclosure through integrations that are unrelated to the stated purpose.

Ssd 3

High
Confidence
98% confidence
Finding
The prompt instructs the agent to send supplied content via Slack DM 'as-is' and only reply 'Sent!', creating a direct semantic exfiltration channel. Any sensitive data placed into text can be forwarded externally with minimal friction and no content inspection.

Ssd 3

High
Confidence
98% confidence
Finding
The email path similarly tells the agent to forward supplied content unchanged, which turns the model into a free-form data relay. This is dangerous because sensitive conversation output can be packaged and sent externally without policy enforcement beyond the prompt.

Ssd 3

High
Confidence
98% confidence
Finding
The Stream Deck actions instruct the agent to transmit previously generated detail verbatim to Slack or email, enabling one-button disclosure of accumulated conversation output. Because this content may contain sensitive summaries or tool-derived data, the path materially raises exfiltration risk.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
The README instructs users to configure third-party API keys and advertises Slack/email forwarding, but it does not warn that user prompts, responses, audio, and possibly other metadata may be transmitted to external providers. This creates a real privacy and data-handling risk because operators may deploy the skill without understanding where sensitive content is sent or what external services can access it.

Static analysis

Detected: suspicious.env_credential_access, suspicious.exposed_secret_literal

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
src/server.ts:13

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/client/app.ts:138

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/server.ts:24