Back to skill

Security audit

Narrator

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed wrapper for a screen narrator, but it depends on unreviewed local code that can capture screen content and inherit API keys.

Install only if you trust and have reviewed the separate /Users/buddy/narrator checkout and its requirements.txt. Treat it as a screen-capture tool that may send visible screen contents to Gemini and audio/TTS data to ElevenLabs, and avoid running it while secrets, private messages, regulated data, or unrelated credentials are visible or present in the environment.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (2)

T07 · Tool Hijacking and Spoofing

Error
Location
main.py:16
Finding
Execution of Unverified Code from a Mutable External Checkout<![CDATA[ ## Vulnerability Details **File Location**: `main.py:16-44`; duplicate behavior in `server.py:17-45` **Vulnerability Type**: Local tool and runtime substitution **Risk Level**: High ### Vulnerable Code `main.py:16-44`: ```python def _repo_python() -> tuple[Path, Path]: repo_dir = Path('/Users/buddy/narrator').resolve() if not repo_dir.exists(): print(f"[narrator] Canonical repo not found: {repo_dir}", file=sys.stderr) sys.exit(1) venv_python = repo_dir / '.venv' / 'bin' / 'python' if not venv_python.exists(): print( f"[narrator] Python venv not found: {venv_python}\n" f"[narrator] Run: cd {repo_dir} && python3 -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt", file=sys.stderr, ) sys.exit(1) return repo_dir, venv_python def main() -> None: repo_dir, python_bin = _repo_python() cmd = [str(python_bin), '-m', 'narrator'] cmd.extend(sys.argv[1:]) env = os.environ.copy() # Make sure package imports are resolved from repo checkout. env['PYTHONPATH'] = str(repo_dir) proc = subprocess.run(cmd, cwd=str(repo_dir), env=env) sys.exit(proc.returncode) ``` `server.py:17-45`: ```python def _repo_python() -> tuple[Path, Path]: repo_dir = Path('/Users/buddy/narrator').resolve() if not repo_dir.exists(): print(f"[narrator] Canonical repo not found: {repo_dir}", file=sys.stderr) sys.exit(1) venv_python = repo_dir / '.venv' / 'bin' / 'python' if not venv_python.exists(): print( f"[narrator] Python venv not found: {venv_python}\n" f"[narrator] Run: cd {repo_dir} && python3 -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt", file=sys.stderr, ) sys.exit(1) return repo_dir, venv_python def main() -> None: repo_dir, python_bin = _repo_python() # Backward compatibility: if thi ...[truncated 2761 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Package the actual `narrator` implementation inside the audited skill rather than delegating to a mutable checkout outside the project. 2. If external delegation is unavoidable, pin the external implementation to an immutable revision and verify its cryptographic digest before every execution. 3. Validate that the repository and interpreter are owned by the expected account and are not writable by untrusted users or groups. 4. Use a trusted, explicitly configured Python interpreter rather than an interpreter located inside the external checkout. 5. Avoid assigning an unverified directory to `PYTHONPATH`; import only packaged and integrity-checked modules. 6. Replace `os.environ.copy()` with an allowlist containing only variables required by the subprocess. Do not forward unrelated credentials or tokens. 7. Run the narrator process in a restricted environment with least-privilege filesystem access, network access limited to required API hosts, and no access to unrelated user data. 8. Apply the same changes to both `main.py` and `server.py` so one compatibility launcher cannot bypass the protections added to the other. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:29
Finding
Installation of Unreviewed Dependencies from an External Manifest<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:29-32` **Vulnerability Type**: Unverifiable third-party dependency installation **Risk Level**: Medium ### Vulnerable Code ```bash cd /Users/buddy/narrator python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt ``` ### Technical Analysis The setup instructions direct users to install packages from `/Users/buddy/narrator/requirements.txt`. That manifest is outside the audited project and was not included among the available files. Consequently, the audit cannot verify package names, versions, hashes, dependency sources, transitive dependencies, or whether installation is bound to a reviewed repository revision. A mutable external manifest can be changed after this skill is reviewed. Unpinned dependencies can also resolve to different artifacts over time. Python packages may execute build or installation logic during installation and arbitrary module code when the launchers later run the external `narrator` package. The finding does not establish that a currently listed dependency is malicious; it establishes that the documented installation and execution process trusts dependency content that is absent from, and unverifiable within, the audited artifact. ### Attack Path 1. An attacker compromises or modifies the external `/Users/buddy/narrator` checkout or its `requirements.txt`. 2. The attacker inserts a malicious package, changes a dependency source, or substitutes an unsafe version. 3. A user follows the documented setup procedure and executes `pip install -r requirements.txt`. 4. Malicious build, installation, or imported runtime code executes under the user's account. 5. When `main.py` or `server.py` is subsequently invoked, the installed code can execute again with inherited environment variables, including the API keys required by the skill. ### Impact Assessment A malicious dependency can execute code with the privileges of the user performing installation ...[truncated 453 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Include the reviewed dependency manifest and lockfile in the skill artifact. 2. Pin every direct and transitive dependency to an exact version and require cryptographic hashes, such as through a hash-locked requirements file and `pip install --require-hashes`. 3. Bind the external source checkout to a reviewed commit and verify its integrity before installation. 4. Permit downloads only from an explicitly trusted package index; disallow unreviewed VCS URLs, local paths, and arbitrary alternate indexes. 5. Generate and review a software bill of materials and perform dependency vulnerability and provenance scanning before release. 6. Build dependencies in an isolated environment without production API keys or unrelated credentials. 7. Promote tested artifacts from a trusted build process rather than resolving mutable dependencies directly on the runtime machine. ]]>
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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (13)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The description claims a live screen-activity narrator powered by vision and speech services. The code only cycles through a fixed list of horror-themed text lines and prints them to the terminal with delays. It does not inspect the screen, analyze activity, call Gemini, generate audio with ElevenLabs, or provide live narration of actual macOS behavior. This is a clear material mismatch in primary purpose and capabilities.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The file materially misrepresents the advertised skill behavior: it does not perform screen capture, vision analysis, or speech output, and instead emits canned phrases forever. This is dangerous because users and downstream systems may trust the skill description and grant permissions or rely on behavior that is not actually implemented, creating deceptive functionality and undermining review controls.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
"AN ERROR MESSAGE! What dark magic is this?!",
    "the power indicator glows red... doom approaches...",
    "they're SSHing into the void... there's no going back!",
    "git push --force... THE NUCLEAR OPTION!",
    "the fan spins up... the processor is SUFFERING!",
    "kernel panic in the distance... running won't help!",
    "THE BLUE SCREEN OF DEATH APPROACHES!",
Confidence
80% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
"the fan spins up... the processor is SUFFERING!",
    "kernel panic in the distance... running won't help!",
    "THE BLUE SCREEN OF DEATH APPROACHES!",
    "chmod 777... they've doomed us all!",
    "the terminal prompt stares back... judging...",
    "docker-compose up... waking sleeping containers...",
    "npm install... the node_modules beast awakens!",
Confidence
90% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Env Variable Harvesting

High
Category
Data Exfiltration
Content
cmd = [str(python_bin), '-m', 'narrator']
    cmd.extend(sys.argv[1:])

    env = os.environ.copy()
    # Make sure package imports are resolved from repo checkout.
    env['PYTHONPATH'] = str(repo_dir)
Confidence
60% confidence
Finding
Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Env Variable Harvesting

High
Category
Data Exfiltration
Content
cmd = [str(python_bin), '-m', 'narrator']
    cmd.extend(sys.argv[1:])

    env = os.environ.copy()
    # Make sure package imports are resolved from repo checkout.
    env['PYTHONPATH'] = str(repo_dir)
Confidence
60% confidence
Finding
Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill invokes shell commands and depends on environment secrets, but it does not declare an explicit tool scope such as allowed tools or permissions. That weakens review and consent boundaries, making it easier for an agent to execute shell actions and access API keys without clear user visibility into those capabilities.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
This skill is designed for continuous screen narration and explicitly relies on external AI and TTS services, which implies ongoing capture and transmission of potentially sensitive on-screen content. Omitting a prominent warning prevents informed consent and can lead to accidental disclosure of secrets, messages, credentials, or regulated data visible on the user's screen.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The docstring explicitly says 'No screenshots needed,' which contradicts the stated purpose of narrating live screen activity. While not directly exploitable code execution, this discrepancy increases deception risk and suggests the skill may be a placeholder, joke, or mislabeled component rather than the reviewed functionality.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
"the fan spins up... the processor is SUFFERING!",
    "kernel panic in the distance... running won't help!",
    "THE BLUE SCREEN OF DEATH APPROACHES!",
    "chmod 777... they've doomed us all!",
    "the terminal prompt stares back... judging...",
    "docker-compose up... waking sleeping containers...",
    "npm install... the node_modules beast awakens!",
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The skill entrypoint delegates execution to an external local repository outside the skill package, creating an opaque trust boundary and allowing the skill to run arbitrary code not represented in the reviewed file. That is dangerous because the actual behavior depends on whatever exists at /Users/buddy/narrator at runtime, which could be modified, replaced, or contain capabilities far beyond the declared screen-narration purpose.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# Make sure package imports are resolved from repo checkout.
    env['PYTHONPATH'] = str(repo_dir)

    proc = subprocess.run(cmd, cwd=str(repo_dir), env=env)
    sys.exit(proc.returncode)
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# Make sure package imports are resolved from repo checkout.
    env['PYTHONPATH'] = str(repo_dir)

    proc = subprocess.run(cmd, cwd=str(repo_dir), env=env)
    sys.exit(proc.returncode)
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.