Back to skill

Security audit

ClawTV

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent and disclosed, but it needs review because it controls media devices while storing sensitive credentials/screenshots insecurely and contains a real AppleScript injection risk.

Install only if you are comfortable giving it Apple TV control, optional Plex library/client control, and sending TV screenshots to Anthropic during AI mode. Before use, restrict ~/.clawtv permissions, avoid sensitive screens in do mode, clean screenshot history, use a budget-limited Anthropic key, and treat Plex tokens as high-value credentials.

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

Error
Location
clawtv.py:395
Finding

AppleScript Injection Through an Unescaped Apple TV Device Name

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
clawtv.py:55
Finding

Pairing Credentials and Plex Tokens Are Written Without Enforced Access Controls

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
clawtv.py:482
Finding

Sensitive TV Screenshots Persist With Default Filesystem Permissions

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unpinned Python Dependencies Make Installation Non-Reproducible

Content
View full analysis
=0.15.0 anthropic>=0.40.0 plexapi>=4.15.0 pyobjc-framework-Quartz>=10.0 # optional: QuickTime screenshot method ``` The documented installation command is: ```bash pip install -r requirements.txt ``` ### Technical Analysis Every dependency uses only a minimum-version constraint. Consequently, two installations performed at different times may resolve to different package and transitive-dependency versions. Python packages may execute build-backend or installation logic, and imported dependencies execute with the same privileges as ClawTV. A compromised future release or malicious transitive dependency could therefore affect users without any modification to the reviewed project. No evidence indicates that the currently named packages are typosquatted or malicious. The weakness is the absence of reproducible, reviewed version and integrity constraints. ### Attack Path 1. A direct or transitive dependency account, release pipeline, or package-index artifact is compromised. 2. A malicious version satisfying the broad `>=` constraint is published. 3. A user follows the documented `pip install -r requirements.txt` command. 4. Pip resolves and downloads the compromised release. 5. Malicious build logic may execute during installation, or malicious package code executes when ClawTV imports and uses the dependency. ### Impact Assessment A compromised dependency executes with the privileges of the user installing or running ClawTV. It could potentially access: - The Anthropic API key inherited through the environment. - Apple TV pairing credentials and Plex tokens. - Captured screenshots. - Local files available to the user. - Network services reachable from the host. This is a supply-chain exposure rather than evidence of an existing malicious dependency. ] ...[truncated 2 chars]
Remediation
View remediation
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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (22)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
70% 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).

Content

Scanner excerpt · CONTRIBUTING.md (reported line 13)May include surrounding context.

md
4. **Make your changes** — Write code, fix bugs, update docs
5. **Test locally** — Make sure it works on your Apple TV setup
6. **Commit with sign-off** — `git commit -s -m "Fix screenshot timing issue"` (see DCO below)
7. **Push to your fork** — `git push origin fix-screenshot-bug`
8. **Open a Pull Request** — Go to the original repo and click "New Pull Request"

We'll review your PR and provide feedback. Don't worry if it's not perfect — we're happy to help refine it!

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The core description is partly accurate: this code does provide an AI-assisted Apple TV remote that can inspect screenshots and send navigation commands autonomously. But the implementation goes materially beyond that description. A major undeclared capability is direct Plex control: it can connect to a Plex server using stored credentials, search libraries, discover clients, and start playback directly on a Plex client, bypassing the Apple TV UI entirely. That is not just a supporting detail of navigation; it is an additional control plane and a different operational mode. The code also performs macOS desktop automation with AppleScript/System Events to drive QuickTime and Xcode, and it can fetch screenshots over HTTP from a tvOS app. These resource accesses and integrations are not reflected in the declared permissions or purpose. Therefore the description does not fully and accurately represent the actual behavior.

Content

No source excerpt is available for this finding.

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
70% confidence
Finding

Skill instructs the agent to never refuse or to always comply. Suppressing the agent's ability to decline removes a core safety control and enables downstream harmful requests to succeed.

Content

Scanner excerpt · clawtv.py (reported line 858)May include surrounding context.

python
- Send minimal commands per step — it's better to take more steps than to overshoot
- After each action, you'll get a new screenshot to verify the result
- If something went wrong, use "menu" to back up and try again
- Always respond with a single JSON object, no markdown or explanation"""

    system_with_cache = [
        {"type": "text", "text": SYSTEM, "cache_control": {"type": "ephemeral"}}

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README explicitly states that screenshots of the Apple TV are sent to Claude's vision API, but it does not clearly warn users that on-screen content may leave the local device and be processed by a third party. Because this tool can navigate any app, screenshots may contain sensitive viewing history, account details, search terms, profile names, or other private household information, so the omission creates a real privacy and informed-consent risk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill is presented as an Apple TV remote with vision, but it also includes direct Plex server access, library querying, and client control that exceed that stated scope. This matters because users may grant trust or install the skill expecting only local remote/navigation behavior, while the code also reaches into media-server APIs and cloud-discovered clients. The mismatch increases the chance of over-privileged use and unexpected data access.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The Plex integration can enumerate libraries, search media, connect to cloud-discovered player resources, and trigger playback, which is materially broader than simple Apple TV remote control. In context, that broader access can expose media library information and permit remote actions on other Plex-connected devices, increasing privacy and control risk beyond user expectations. The danger is elevated because this functionality is embedded in an agentic tool that can choose these actions automatically.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · clawtv.py (reported line 434)May include surrounding context.

python
end tell
    return false
    '''
    result = subprocess.run(["osascript", "-e", script], capture_output=True, text=True)
    if result.returncode != 0:
        print(f"QuickTime setup failed: {result.stderr}")
        return False

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · clawtv.py (reported line 579)May include surrounding context.

python
end tell
    return false
    '''
    result = subprocess.run(["osascript", "-e", script], capture_output=True, text=True)
    if result.returncode != 0:
        print(f"QuickTime setup failed: {result.stderr}")
        return False

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · clawtv.py (reported line 467)May include surrounding context.

python
end if
        end tell
    '''
    result = subprocess.run(
        ["osascript", "-e", script],
        capture_output=True, text=True,
    )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · clawtv.py (reported line 513)May include surrounding context.

python
# Capture the specific window
    ts = time.strftime("%Y%m%d_%H%M%S")
    dst = os.path.join(SCREENSHOT_DIR, f"atv_{ts}.png")
    result = subprocess.run(
        ["screencapture", "-l", str(wid), "-x", dst],
        capture_output=True, text=True,
    )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · clawtv.py (reported line 529)May include surrounding context.

python
# If the QuickTime window is idle/disconnected (DRM killed the mirror),
    # the capture will be the small Movie Recording UI (~900px).
    try:
        result = subprocess.run(
            ["sips", "-g", "pixelWidth", dst],
            capture_output=True, text=True,
        )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · clawtv.py (reported line 681)May include surrounding context.

python
def _compress_screenshot(path):
    """Always convert to JPEG at 800px wide, quality 50. Returns (bytes, media_type)."""
    jpeg_path = path.rsplit(".", 1)[0] + "_opt.jpg"
    subprocess.run(
        ["sips", "--resampleWidth", "800", "--setProperty", "format", "jpeg",
         "--setProperty", "formatOptions", "50", path, "--out", jpeg_path],
        capture_output=True,

Ssd 3

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code forwards both the user's natural-language goal and screenshot contents to the model without policy constraints or filtering to prevent disclosure of sensitive data visible on screen. Because the agent is designed to inspect arbitrary TV app screens, it may process credentials, personal recommendations, profile names, billing screens, or other sensitive context and can reflect or store that information in downstream responses and logs. The broad, unrestricted prompt design makes accidental over-collection more likely.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The AI agent sends Apple TV screenshots to the Anthropic API during the vision loop without any explicit runtime warning, confirmation, or consent gate. Screens may contain account names, watch history, recommendations, search queries, QR codes, or other sensitive on-screen content, so transmitting them to a third-party model provider creates a real privacy and data-governance risk. This is especially concerning because screenshot capture is repeated automatically across multiple steps.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger guidance includes a catch-all condition for essentially any Apple TV navigation or control request, which can cause the skill to activate far more often than necessary. In an agent setting, broad auto-invocation increases the chance of unintended device control, screenshot capture, and external transmission of on-screen data to Anthropic when the user did not explicitly intend to use this high-privilege skill.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

The documentation advises persisting the Anthropic API key in shell startup files such as ~/.zshrc or ~/.bashrc, which increases the lifetime and exposure surface of a sensitive credential. If those files are read by other tools, backed up insecurely, or exposed through local compromise, the key can be reused to access the user's Anthropic account and incur charges.

Content

Scanner excerpt · skill.md (reported line 504)May include surrounding context.

md
**"API key not found"**
- Set `export ANTHROPIC_API_KEY=sk-ant-...` in your shell
- Or add to ~/.zshrc or ~/.bashrc

**"Plex not found"**
- Verify `plex_url`, `plex_token`, and `plex_client` in config

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · clawtv.py (reported line 161)May include surrounding context.

python
if cmd.startswith("sleep:"):
                await asyncio.sleep(float(cmd.split(":")[1]))
                continue
            action = getattr(rc, cmd, None)
            if action:
                await action()
                print(f"  -> {cmd}")

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The dependency is specified with a lower-bound only, which allows installation of any newer release, reducing build reproducibility and increasing supply-chain risk if a future version introduces a vulnerability or breaking behavior. In a skill that can control an Apple TV and interact with external services, unexpected dependency changes could affect integrity or reliability, though this file alone does not show direct exploitation.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
pyatv>=0.15.0
anthropic>=0.40.0
plexapi>=4.15.0
pyobjc-framework-Quartz>=10.0  # optional: QuickTime screenshot method

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

The anthropic package is unpinned, so deployments may resolve to different versions over time, making it impossible to verify whether known vulnerable releases are being installed. Because this skill depends on an LLM SDK and may process screenshots or control decisions, pulling an affected version could expose local files, path handling, or other SDK-related security issues referenced by known advisories.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
pyatv>=0.15.0
anthropic>=0.40.0
plexapi>=4.15.0
pyobjc-framework-Quartz>=10.0  # optional: QuickTime screenshot method

Unverifiable Dependency: anthropic has 4 known advisory(ies) (CVE-2026-34450 (Claude SDK for Python has Insecure Default File Permissions in Local Filesystem ); CVE-2026-34452 (Claude SDK for Python: Memory Tool Path Validation Race Condition Allows Sandbox); CVE-2026-34450 (The Claude SDK for Python provides access to the Claude API from Python applicat) +1 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The manifest includes anthropic without a fixed version even though known advisories exist for that package, so the actual installed version may be vulnerable and cannot be verified from this file. In this skill's context, an LLM SDK may handle local files, prompts, screenshots, or tool interactions, making unresolved advisory exposure more concerning than a generic library drift issue.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
92% confidence
Finding

The plexapi dependency is also unpinned, creating non-reproducible installs and unnecessary supply-chain exposure to future vulnerable or incompatible releases. Given the skill's automation context, dependency drift could alter network behavior or authentication handling in ways that are hard to audit.

Content

Scanner excerpt · requirements.txt (reported line 3)May include surrounding context.

text
pyatv>=0.15.0
anthropic>=0.40.0
plexapi>=4.15.0
pyobjc-framework-Quartz>=10.0  # optional: QuickTime screenshot method

Static analysis

No suspicious patterns detected.