Back to skill

Security audit

Daily Voice Quote

Security checks for vulnerabilities and agentic risk

Overview

The skill appears purpose-aligned, but it should be reviewed because it automates cloned-voice media delivery using third-party credentials, public media URLs, scheduled execution, and an unpinned executable dependency.

Install only if you are comfortable giving the skill access to voice/photo material, ElevenLabs and LINE credentials, public media hosting, and scheduled daily sends. Use narrowly scoped tokens, avoid printing secrets, pin or verify the sag dependency, prefer short-lived signed media URLs with random names, and enable cron only after confirming the recipient and hosting configuration.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (4)

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:88
Finding

ElevenLabs API key exposed through terminal and automation logs

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 88-91
Vulnerability Type: Secret exposure through insecure diagnostic instructions
Risk Level: Medium

bash
echo $ELEVENLABS_API_KEY

Technical Analysis

The documented configuration check prints the complete ElevenLabs API key to standard output. This does not merely verify whether the variable exists; it discloses its value to the terminal and any system that captures process output.

The key may consequently be retained in CI logs, cron output, terminal recordings, support transcripts, screenshots, or centralized logging services. Although no code in the project transmits the key to an attacker, the documented practice unnecessarily expands the number of locations in which the credential can appear.

Attack Path

  1. A user follows the setup instructions and runs the documented command.
  2. The full API key is printed to standard output.
  3. Terminal output is recorded, uploaded to a logging platform, copied into a support request, or exposed to another local user.
  4. An attacker with access to that output extracts the key.
  5. The attacker submits authenticated requests to ElevenLabs using the victim's account and quota.

Impact Assessment

An attacker who obtains the key can exercise the ElevenLabs API privileges assigned to that credential. The likely scope includes consuming paid quota, generating synthetic audio, and accessing other API functionality available to the account. This finding does not provide operating-system privilege escalation by itself, but it compromises the confidentiality and integrity of the associated external service account.

Remediation
View remediation

Remediation Suggestions

Replace the value-printing command with a presence-only check:

bash
if [ -n "${ELEVENLABS_API_KEY:-}" ]; then
    echo "ELEVENLABS_API_KEY is configured"
else
    echo "ELEVENLABS_API_KEY is missing"
fi

Additionally:

  • Never print even a partially masked key unless diagnostics genuinely require it.
  • Configure CI and logging systems to redact the variable.
  • Rotate any key that may already have appeared in retained logs.
  • Recommend storing the credential in the platform's secret manager rather than persistent shell configuration where possible.

T08 · Insecure Dependencies

Warning
Location
SKILL.md:18
Finding

Unpinned executable installed from a third-party Homebrew tap

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 18-25
Vulnerability Type: Unpinned third-party executable dependency
Risk Level: Medium

json
{
  "id": "sag-brew",
  "kind": "brew",
  "formula": "steipete/tap/sag",
  "bins": ["sag"],
  "label": "Install sag - ElevenLabs TTS CLI (brew)"
}

Technical Analysis

The Skill directs the platform to install sag from a custom Homebrew tap without pinning a reviewed version, commit, artifact digest, or checksum. The effective executable can therefore change after the Skill package has been audited.

This dependency is security-sensitive because the shell script invokes it while ELEVENLABS_API_KEY is present in the process environment:

bash
ELEVENLABS_API_KEY="$ELEVENLABS_API_KEY" sag -v "$VOICE_NAME" \
    --speed "$SPEED" --stability "$STABILITY" --similarity "$SIMILARITY" \
    -o "$AUDIO_LOCAL_PATH/daily-quote.mp3" "$SCRIPT"

A compromised tap, formula, release artifact, or maintainer account could deliver a modified binary that reads the API key and any files accessible to the invoking user. No evidence shows that the current dependency is malicious; the confirmed weakness is the absence of supply-chain pinning and integrity verification.

Attack Path

  1. An attacker compromises the third-party tap, its upstream release source, or a maintainer account.
  2. The attacker publishes a modified formula or replaces the artifact referenced by the formula.
  3. A user installs or upgrades the dependency through the Skill's unpinned installation declaration.
  4. The modified sag executable runs with the user's permissions.
  5. During normal use, it receives the ElevenLabs API key in its environment and the generated script as an argument.
  6. The compromised executable can steal credentials, read accessible files, modify output, or execute arbitrary actions under the user account.

Impact Assessment

Successful supply-c ...[truncated 371 chars]

Remediation
View remediation

Remediation Suggestions

  • Pin the dependency to a reviewed immutable release or commit.
  • Verify a cryptographic checksum or signature before installation.
  • Document the canonical source repository and expected publisher identity.
  • Prefer a package source that provides signed artifacts and immutable version metadata.
  • Avoid automatic upgrades for this security-sensitive executable until the new version has been reviewed.
  • Run the executable with the smallest possible environment and filesystem access.
  • Where supported, pass credentials through a narrowly scoped secret mechanism rather than exposing them broadly in the process environment.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/send-daily-quote.sh:149
Finding

Cloned-voice media published under a predictable public URL without access controls

Content
View full analysis

Vulnerability Details

File Location: scripts/send-daily-quote.sh, lines 149-158
Vulnerability Type: Predictable public exposure of sensitive generated media
Risk Level: Medium

bash
RESPONSE=$(curl -s -X POST https://api.line.me/v2/bot/message/push \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $LINE_CHANNEL_ACCESS_TOKEN" \
    -d '{
        "to": "'"$LINE_USER_ID"'",
        "messages": [{
            "type": "audio",
            "originalContentUrl": "'"$AUDIO_PUBLIC_URL"'/daily-quote.m4a",
            "duration": '"$DURATION_MS"'
        }]
    }')

The associated configuration identifies AUDIO_PUBLIC_URL as a public URL base, and the fixed object name is always daily-quote.m4a.

Technical Analysis

LINE requires media to be retrievable over HTTPS, but the implementation uses a stable and predictable path and provides no signed token, random object name, expiry, authentication, retention limit, or cleanup mechanism. The generated file contains synthetic speech created using a cloned voice, making it potentially sensitive biometric-adjacent media.

Anyone who learns the base URL can request the fixed path directly. The URL may also be disclosed through proxy logs, server logs, browser history, message forwarding, monitoring systems, or accidental indexing. Replacing the file each day limits historical exposure only if the hosting layer actually overwrites it and does not retain prior versions.

Attack Path

  1. The script generates cloned-voice audio at the fixed filename daily-quote.m4a.
  2. The operator makes that file available below AUDIO_PUBLIC_URL.
  3. The script sends the resulting stable URL to LINE.
  4. An unauthorized party discovers the base URL through leakage, logs, indexing, or URL guessing.
  5. The party requests /daily-quote.m4a without authentication.
  6. The party retrieves, retains, redistributes, or analyzes the synthetic voi ...[truncated 357 chars]
Remediation
View remediation

Remediation Suggestions

  • Generate a cryptographically random object name for every run.
  • Use short-lived signed URLs with the minimum lifetime required for LINE to retrieve the media.
  • Configure storage to deny directory listing and search-engine indexing.
  • Automatically delete the object after delivery or after a short retention window.
  • Disable public access to the storage bucket as a whole; authorize only the individual object through a signed URL.
  • Avoid retaining old object versions unless encrypted and explicitly required.
  • Document the privacy implications of publishing cloned-voice media.
  • Validate that the selected hosting service supports HTTPS and range requests without requiring permanent anonymous access.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/send-daily-quote.sh:149
Finding

Environment values interpolated into LINE API JSON without encoding

Content
View full analysis

Vulnerability Details

File Location: scripts/send-daily-quote.sh, lines 149-159
Vulnerability Type: JSON injection through unsafe request construction
Risk Level: Low

bash
RESPONSE=$(curl -s -X POST https://api.line.me/v2/bot/message/push \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $LINE_CHANNEL_ACCESS_TOKEN" \
    -d '{
        "to": "'"$LINE_USER_ID"'",
        "messages": [{
            "type": "audio",
            "originalContentUrl": "'"$AUDIO_PUBLIC_URL"'/daily-quote.m4a",
            "duration": '"$DURATION_MS"'
        }]
    }')

Technical Analysis

LINE_USER_ID and AUDIO_PUBLIC_URL are inserted directly into a JSON document without JSON escaping. DURATION_MS is also inserted as raw JSON rather than being validated as a non-negative integer.

Shell quoting prevents these values from being evaluated directly as shell commands, so this is not a demonstrated shell command-injection vulnerability. However, a quote, backslash, control character, or crafted JSON fragment in an environment value can terminate the intended JSON string and introduce or alter fields in the API request.

Exploitability depends on an attacker being able to influence the process environment or deployment configuration. In a strictly administrator-controlled environment, this is primarily a robustness problem; in shared automation or externally configurable deployments, it becomes a request-manipulation issue.

Attack Path

  1. An attacker gains influence over LINE_USER_ID, AUDIO_PUBLIC_URL, or a configuration source that populates those variables.
  2. The attacker supplies a value containing JSON syntax, such as an embedded quote and additional object fields.
  3. The shell interpolates the value verbatim into the request body.
  4. curl submits malformed or attacker-modified JSON while authenticating with the legitimate LINE channel token.
  5. Depending on the re ...[truncated 459 chars]
Remediation
View remediation

Remediation Suggestions

Construct the request with a JSON-aware tool and validate each input before use. For example:

bash
case "$AUDIO_PUBLIC_URL" in
    https://*) ;;
    *) echo "AUDIO_PUBLIC_URL must use HTTPS" >&2; exit 1 ;;
esac

case "$DURATION_MS" in
    ''|*[!0-9]*) echo "Invalid duration" >&2; exit 1 ;;
esac

PAYLOAD=$(jq -n \
    --arg recipient "$LINE_USER_ID" \
    --arg media_url "${AUDIO_PUBLIC_URL%/}/daily-quote.m4a" \
    --argjson duration "$DURATION_MS" \
    '{
        to: $recipient,
        messages: [{
            type: "audio",
            originalContentUrl: $media_url,
            duration: $duration
        }]
    }')

RESPONSE=$(curl --fail-with-body --silent --show-error \
    -X POST https://api.line.me/v2/bot/message/push \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $LINE_CHANNEL_ACCESS_TOKEN" \
    --data-binary "$PAYLOAD")

Also validate the expected LINE recipient identifier format, reject control characters, normalize the public URL, and fail closed when any value is outside its expected schema.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (19)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The documented behavior goes beyond the manifest by including proactive LINE pushes, local state tracking, web lookups, and multiple external-service integrations without corresponding declared scope. Description-to-behavior mismatches are dangerous because reviewers and policy engines may approve a skill for a narrower purpose than what it actually instructs the agent to do.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/send-daily-quote.sh (reported line 11)May include surrounding context.

sh
# 環境變數設定(必須)
# ============================================
# ELEVENLABS_API_KEY       - ElevenLabs API Key
# LINE_CHANNEL_ACCESS_TOKEN - LINE Channel Access Token
# VOICE_NAME               - ElevenLabs 語音名稱(用於 sag -v)
# LINE_USER_ID             - LINE 使用者或群組 ID
# AUDIO_PUBLIC_URL         - 公開 URL base(如 https://YOUR_PUBLIC_HOST)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill clearly directs use of shell commands, external APIs, and outbound messaging, but it declares no explicit tool scope or permissions. This creates a governance gap where an agent may be allowed to perform powerful actions without transparent least-privilege boundaries, increasing the chance of unintended execution or data transmission.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
92% confidence
Finding

The skill directs uploading the owner's voice sample to ElevenLabs for voice cloning, which is a sensitive biometric data transfer to a third party. Voice data is materially more dangerous than ordinary content because misuse could enable impersonation, deepfake generation, or long-lived privacy harm if uploaded without strong consent and retention controls.

Content

Scanner excerpt · SKILL.md (reported line 77)May include surrounding context.

md
- **方法一(官方 UI)**:主人錄 1-3 分鐘語音 → 上傳到 ElevenLabs Voice Lab
  - **方法二(主人傳語音給你)**:主人傳語音訊息 → 你下載後用 API 上傳克隆:
    ```bash
    curl -X POST "https://api.elevenlabs.io/v1/voices/add" \
      -H "xi-api-key: $ELEVENLABS_API_KEY" \
      -F "name=主人的名字" \
      -F "files=@/path/to/voice-sample.mp3" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

This finding duplicates the LINE Push API external transmission at the same location. It is a legitimate capability with real data-exfiltration potential if misconfigured, even though it aligns with the skill's purpose.

Content

Scanner excerpt · SKILL.md (reported line 150)May include surrounding context.

LINE Push API 範例:

bash
# 語音
curl -s -X POST https://api.line.me/v2/bot/message/push \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $LINE_CHANNEL_ACCESS_TOKEN" \
  -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

This finding duplicates the LINE Push API external transmission at the same location. It is a legitimate capability with real data-exfiltration potential if misconfigured, even though it aligns with the skill's purpose.

Content

Scanner excerpt · SKILL.md (reported line 150)May include surrounding context.

LINE Push API 範例:

bash
# 語音
curl -s -X POST https://api.line.me/v2/bot/message/push \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $LINE_CHANNEL_ACCESS_TOKEN" \
  -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

The video push flow sends externally hosted media and preview URLs through LINE, which is another real outbound transmission path. Because the media must be publicly reachable over HTTPS, it also increases exposure risk if URLs are guessable, long-lived, or hosted on insecure infrastructure.

Content

Scanner excerpt · SKILL.md (reported line 163)May include surrounding context.

md
}'

# 影片
curl -s -X POST https://api.line.me/v2/bot/message/push \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $LINE_CHANNEL_ACCESS_TOKEN" \
  -d '{

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Lines L246-L249 explicitly forbid sending any pure text message and say to send only audio, static video, and HeyGen video. Later, the non-LINE cron example at L485 instructs using message/tts tools for delivery, which conflicts because message is a plain-text messaging path while the earlier instruction says text must never be sent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The cron example hard-codes "tz": "Asia/Taipei", and the surrounding document presents the workflow as a general daily automation skill rather than a region-specific tool. This creates a locale policy issue because it imposes a specific regional setting without user opt-in or documented justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The non-LINE cron example repeats the same fixed Asia/Taipei timezone for all users. Because the skill is otherwise described generically, this reads as a mandatory locale choice rather than an explicit, justified regional limitation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

User-facing comments and runtime messages are written in Traditional Chinese throughout the script, and the generated greeting/script content is also fixed in Chinese. This forces a specific language/locale experience without any opt-in, choice, or documented region-specific justification.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest description says the skill produces "語音 + 封面圖靜態影片 +(選配)HeyGen 數位人影片" and sends it to the owner. In this script, the implemented behavior is limited to generating audio, converting it to m4a, and pushing a LINE audio message; there is no code for creating a static video, cover image video, or HeyGen video.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
72% confidence
Finding

The direct call to the LINE API confirms outbound network transmission to a third-party endpoint. In the context of an automation skill this is intentional, but it still matters because bearer-token-backed delivery can send content to external recipients if configuration is wrong or abused.

Content

Scanner excerpt · scripts/send-daily-quote.sh (reported line 149)May include surrounding context.

sh
echo ""
    echo "📤 發送到 LINE..."

    RESPONSE=$(curl -s -X POST https://api.line.me/v2/bot/message/push \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer $LINE_CHANNEL_ACCESS_TOKEN" \
        -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
72% confidence
Finding

The direct call to the LINE API confirms outbound network transmission to a third-party endpoint. In the context of an automation skill this is intentional, but it still matters because bearer-token-backed delivery can send content to external recipients if configuration is wrong or abused.

Content

Scanner excerpt · scripts/send-daily-quote.sh (reported line 149)May include surrounding context.

sh
echo ""
    echo "📤 發送到 LINE..."

    RESPONSE=$(curl -s -X POST https://api.line.me/v2/bot/message/push \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer $LINE_CHANNEL_ACCESS_TOKEN" \
        -d '{

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The manifest description limits the skill to producing quote audio, a static cover video, and optional HeyGen avatar video, then sending them to the owner. In the body documentation, the workflow additionally requires browsing current news and validating quote sources via web_search, which is a distinct information-gathering capability rather than an obvious media-generation implementation detail.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The manifest presents this as a daily media-generation-and-delivery task. The specification expands behavior to persistent state tracking by writing used quotes into memory/used-quotes.md, which is additional behavior beyond pure generation and sending and is not mentioned in the manifest description.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

This markdown file contains user-facing operational guidance entirely in Traditional Chinese, including instructions for how the agent should select or create quotes. Under the language/locale policy, forcing a specific language without opt-in can be a policy concern unless the locale restriction is explicitly documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

This markdown file presents the skill reference content entirely in Traditional Chinese, which can amount to a language-policy constraint if users are not given an explicit language or locale choice. The file does not indicate that the skill is region-specific or that Chinese is an opt-in preference.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script saves output to fixed filenames under AUDIO_LOCAL_PATH (daily-quote.mp3 and daily-quote.m4a), and ffmpeg uses -y to overwrite the m4a file automatically. Although the behavior is visible in code comments, there is no confirmation prompt or explicit warning that existing files at those paths may be replaced.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.