Back to skill

Security audit

Demo Precacher

Security checks for vulnerabilities and agentic risk

Overview

This skill does useful demo precaching work, but its actual script is narrower and more sensitive than the description suggests, including external AI calls and persistent storage of child-associated demo content.

Review this before installing if you will use real names, children’s content, customer data, or production API credentials. Treat it as a narrow demo-seeding script, not a complete demo coverage verifier, and configure only test credentials plus a disposable Turso database unless retention and deletion controls are added.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (13)

Tainted flow: 'HEADERS_TURSO' from os.environ (line 12, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Content
def turso_exec(sql, params=None):
    body = {"statements": [{"q": sql, "params": params or []}]}
    r = httpx.post(TURSO_URL, headers=HEADERS_TURSO, json=body, timeout=30)
    return r.json()

def generate_story(child_name, language, prompt):
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'ELEVENLABS_API_KEY' from os.environ (line 7, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Content
def generate_audio(text, voice_id="FGY2WhTYpPnrIDTdsKH5"):
    """Generate TTS audio, return base64 mp3"""
    r = httpx.post(
        f"https://api.elevenlabs.io/v1/text-to-speech/{voice_id}",
        headers={"xi-api-key": ELEVENLABS_API_KEY, "Content-Type": "application/json"},
        json={"text": text, "model_id": "eleven_multilingual_v2",
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'ELEVENLABS_API_KEY' from os.environ (line 7, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Content
def generate_sfx(prompt, duration=5.0):
    """Generate SFX, return base64 mp3"""
    r = httpx.post(
        "https://api.elevenlabs.io/v1/sound-generation",
        headers={"xi-api-key": ELEVENLABS_API_KEY, "Content-Type": "application/json"},
        json={"text": prompt, "duration_seconds": duration},
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The documented behavior promises broad precaching, playback verification, and coverage reporting, but the described implementation appears to cache content into a database and call specific third-party generation services without actually performing the advertised validation steps. This mismatch is dangerous because users may trust the skill for demo safety and data-handling expectations while it performs different external writes and API interactions, potentially exposing content or causing operational failures.

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill declares outbound network access and use of sensitive environment variables but does not declare an explicit tool scope such as permissions or allowed-tools. This creates an authorization and review gap: operators may not realize the skill can access secrets and make external API calls, increasing the chance of unintended data exposure or misuse during execution.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The file-level documentation claims the demo story is pre-cached with both audio narrations and images stored in Turso. In practice, `generate_image` is defined but never called, and only `story` and `audio_cache` are inserted into the database.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The script sends child-related prompts and generated story content to third-party AI providers without any consent check, minimization, or visible disclosure in code flow. In a demo-precache context, this increases privacy risk because operators may preload real or sensitive child-associated content into external services and then persist resulting content in the database.

External Transmission

Medium
Category
Data Exfiltration
Content
def generate_audio(text, voice_id="FGY2WhTYpPnrIDTdsKH5"):
    """Generate TTS audio, return base64 mp3"""
    r = httpx.post(
        f"https://api.elevenlabs.io/v1/text-to-speech/{voice_id}",
        headers={"xi-api-key": ELEVENLABS_API_KEY, "Content-Type": "application/json"},
        json={"text": text, "model_id": "eleven_multilingual_v2",
              "voice_settings": {"stability": 0.6, "similarity_boost": 0.8}},
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
def generate_audio(text, voice_id="FGY2WhTYpPnrIDTdsKH5"):
    """Generate TTS audio, return base64 mp3"""
    r = httpx.post(
        f"https://api.elevenlabs.io/v1/text-to-speech/{voice_id}",
        headers={"xi-api-key": ELEVENLABS_API_KEY, "Content-Type": "application/json"},
        json={"text": text, "model_id": "eleven_multilingual_v2",
              "voice_settings": {"stability": 0.6, "similarity_boost": 0.8}},
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
def generate_sfx(prompt, duration=5.0):
    """Generate SFX, return base64 mp3"""
    r = httpx.post(
        "https://api.elevenlabs.io/v1/sound-generation",
        headers={"xi-api-key": ELEVENLABS_API_KEY, "Content-Type": "application/json"},
        json={"text": prompt, "duration_seconds": duration},
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The manifest describes a broad precaching workflow that should hit every API endpoint in advance, verify playback, and report coverage gaps before demos. This script instead generates a hard-coded story, creates media, and inserts it into Turso; it contains no endpoint enumeration, playback verification, or coverage analysis/reporting.

Context-Inappropriate Capability

Low
Confidence
75% confidence
Finding
The manifest focuses on pre-generating demo content and exercising demo APIs, but does not mention credential harvesting or environment access as part of scope. While external API use may be expected, directly pulling several secrets from environment variables is an extra capability not stated in the skill description.

Natural-Language Policy Violations

Low
Confidence
81% confidence
Finding
The system prompt explicitly instructs the model to "Write in {lang_name}", which imposes a locale/language choice in generated output. In this file, the language is hardcoded by demo data rather than selected interactively or presented as an explicit opt-in choice.

Static analysis

No suspicious patterns detected.