Back to skill

Security audit

Voice Notes Pro

Security checks for vulnerabilities and agentic risk

Overview

The skill’s voice-note purpose is mostly coherent, but its implementation can read any message-supplied local file path and upload the bytes to OpenAI, which is a material security concern.

Review before installing. This skill should only run in a tightly sandboxed account with access limited to the intended WhatsApp media directory and notes folder. Do not run it as root or with broad filesystem access unless the path-validation issue is fixed. Expect voice audio and transcriptions, including possible personal data, to be sent to OpenAI and saved locally in Markdown files.

Vulnerability Patterns
  • 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
  • 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
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
voice-notes-pro.js:318
Finding

Message-Controlled File Path Enables Arbitrary Local File Disclosure to OpenAI

Content
View full analysis

Vulnerability Details

File Location: voice-notes-pro.js:58-67, 318-337
Vulnerability Type: Arbitrary local file read and external data disclosure
Risk Level: High

Vulnerable Code

js
async function transcribeAudio(audioPath) {
  try {
    const client = getOpenAIClient();
    const audioFile = await fs.readFile(audioPath);

    const response = await client.audio.transcriptions.create({
      file: audioFile,
      model: CONFIG.whisper.model,
      language: CONFIG.whisper.language,
    });

    return response.text;
js
async execute({ message, context }) {
  // Check whether the message contains an audio or voice attachment
  if (!message.audio && !message.voice) {
    return {
      success: false,
      message: 'Ten skill obsuguje tylko notatki gosowe',
    };
  }

  // Obtain the audio file path
  const audioPath = message.audio?.path || message.voice?.path;
  if (!audioPath) {
    return {
      success: false,
      message: 'Nie znaleziono pliku audio',
    };
  }

  // Process the voice note
  const result = await processVoiceNote(audioPath);

Technical Analysis

The Skill obtains audioPath directly from the incoming message.audio.path or message.voice.path property and passes it to fs.readFile() without applying any security validation.

The implementation does not:

  • Resolve and validate the canonical path.
  • Restrict access to a dedicated media-upload directory.
  • reject absolute paths or directory traversal.
  • Reject symbolic links.
  • Verify that the target is a regular file.
  • Validate the file extension, MIME type, or audio signature.
  • Enforce a maximum file size.

Consequently, any party capable of controlling the relevant message metadata can cause the Skill process to read an arbitrary file available under its operating-system privileges. The bytes are then supplied as the file value to `client.audi ...[truncated 1997 chars]

Remediation
View remediation

Remediation Suggestions

  1. Do not accept a raw filesystem path from message-controlled data. Use a trusted attachment identifier or stream supplied and validated by the OpenClaw runtime.
  2. Define a dedicated media-upload root and resolve both the allowed root and candidate path with fs.realpath(). Reject the request unless the candidate remains strictly inside that root.
  3. Reject absolute paths and traversal components before resolution as defense in depth.
  4. Use fs.lstat() and fs.stat() to reject symbolic links and require a regular file.
  5. Validate an allowlist of supported audio formats using file signatures, not only extensions or client-provided MIME types.
  6. Enforce a conservative maximum file size before reading or uploading the file. Prefer bounded streaming where supported.
  7. Run the Skill under a dedicated, unprivileged operating-system account with access only to required media and note directories. Avoid running it as root.
  8. Return generic errors to users and avoid exposing local paths or provider details.
  9. Add automated tests covering absolute paths, ../ traversal, symlink escapes, non-audio files, oversized files, and paths outside the approved media directory.

Example containment logic should compare canonical paths with a separator-aware prefix:

js
const uploadRoot = await fs.realpath('/var/lib/openclaw/uploads');
const candidate = await fs.realpath(audioPath);

if (
  candidate !== uploadRoot &&
  !candidate.startsWith(uploadRoot + path.sep)
) {
  throw new Error('Unauthorized attachment path');
}

const stat = await fs.stat(candidate);
if (!stat.isFile() || stat.size > MAX_AUDIO_BYTES) {
  throw new Error('Invalid audio attachment');
}
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (11)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The description highlights transcription and storage features but does not clearly warn that voice content is sent to an external service (Whisper API) and persisted to local Markdown files. Users may unknowingly expose sensitive voice data, personal information, or confidential content to third-party processing and long-term local retention.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill explicitly supports a people database but does not warn that it stores personal profile data locally, including names and biographical details. This can lead to collection and retention of third-party personal data without transparency, increasing privacy and compliance risks if the notes directory is exposed or backed up insecurely.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger list is broad and maps common everyday phrases like task, shopping, idea, or contact-related language to automatic processing of WhatsApp voice notes. This increases the chance of unintended activation, causing private speech to be transcribed, categorized, and written to local files without clear user intent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The configuration sets "language": "pl", which imposes a specific language/locale behavior. Although the document later says it supports Polish and English notes, this setting still hard-codes Polish rather than offering a user-selectable option or documenting a justified locale restriction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The description is written in Polish and appears to present the skill in a specific language/locale without indicating user choice or multilingual support. This can cause unintended invocation or misaligned handling for users in other locales, which is a policy/safety concern, though the direct security impact is limited in this package metadata alone.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The transcription configuration hard-codes language: 'pl', and the skill also formats timestamps using the Polish locale and Warsaw timezone. This imposes a specific language/locale behavior without any visible user opt-in or documented region-specific justification.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The stated purpose says the skill performs intelligent transcription and categorization of voice notes, but the code additionally depends on reading sensitive environment credentials and using them to call an external service. With no manifest permissions or disclosure of external processing, this is a broader capability than the description itself communicates.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Audio from voice notes is sent to an external OpenAI service without any user-facing disclosure or consent mechanism. Because voice notes may contain sensitive personal data, this can cause unintended third-party data exposure and compliance/privacy issues even if the feature is functionally intended.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill persists transcribed content into multiple local note files and directories without warning the user that spoken content will be stored long-term. This can leak sensitive personal or organizational information into broadly accessible local files, especially on shared or poorly permissioned systems.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The manifest description says the skill performs transcription and categorization of voice notes via WhatsApp, but it does not specify concrete trigger phrases, invocation boundaries, or exclusion conditions. In a manifest file, this kind of broad capability description can create ambiguity about when the skill should activate versus when general conversation about notes or WhatsApp should not trigger it.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency on openai uses a caret range (^4.28.0), which permits automatic installation of newer minor/patch releases. This increases supply-chain risk because behavior or transitive code can change without explicit review, potentially introducing vulnerabilities or breaking security assumptions.

Content

Scanner excerpt · package.json (reported line 21)May include surrounding context.

json
"author": "Toniacz",
  "license": "MIT",
  "dependencies": {
    "openai": "^4.28.0"
  }
}

Static analysis

No suspicious patterns detected.