Back to skill

Security audit

Sony Tv

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it claims, but it controls a real TV using a reusable local credential that is stored and sent with limited protection or warning.

Review before installing. Use this only on a trusted local network, choose a strong TV PSK, keep the generated .env file private and out of backups or source control, and prefer explicit TV-related commands so normal requests like play or pause do not unexpectedly control the device. Rotate the TV PSK if the .env file or local network traffic may have been exposed.

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

T08 · Insecure Dependencies

Warning
Location
scripts/tv_control.py:1
Finding

Unpinned Runtime Dependencies Permit Supply-Chain Code Execution

Content
View full analysis

Vulnerability Details

File Location: scripts/tv_control.py:1-7; execution documented in SKILL.md:29-32 and README.md:26-28
Vulnerability Type: Unpinned third-party dependencies resolved at runtime
Risk Level: Medium

Vulnerable Code

python
# /// script
# requires-python = ">=3.10"
# dependencies = [
#     "requests",
#     "wakeonlan",
# ]
# ///

The documented invocation causes uv to resolve these dependencies:

bash
uv run {baseDir}/scripts/tv_control.py --action <action> [--value <n>] [--app <name>] [--buttons <buttons>]

Technical Analysis

The requests and wakeonlan dependencies have no exact version constraints, package hashes, or committed lockfile. When the documented uv run command is executed in an environment where these packages are not already locked and cached, uv may resolve and install whichever compatible releases are available at that time.

Consequently, the effective executable code can change without any modification to the reviewed project. If an upstream package, maintainer account, package index, or dependency in the transitive dependency graph is compromised, a malicious release could be selected automatically. Python package installation and import behavior can execute package-controlled code with the privileges of the user running the Skill.

Attack Path

  1. An attacker compromises a declared package, one of its transitive dependencies, a package maintainer account, or the package distribution channel.
  2. The attacker publishes a malicious version that satisfies the unconstrained dependency declaration.
  3. A user or Agent invokes the documented uv run scripts/tv_control.py command in a fresh or newly resolved environment.
  4. uv resolves and installs the malicious compatible release.
  5. Malicious package code executes during installation or import when requests or wakeonlan is loaded.
  6. The pay ...[truncated 669 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin every direct dependency to an exact reviewed version rather than using unconstrained package names.
  2. Generate and commit a lockfile that includes the complete transitive dependency graph.
  3. Require cryptographic hashes for downloaded distributions where the tooling supports hash verification.
  4. Configure uv to use an explicitly trusted package index and prevent fallback to unexpected indexes.
  5. Review dependency updates before changing the lockfile and use automated vulnerability and provenance scanning.
  6. Run the Skill with a minimally privileged account and expose only the environment variables required for TV control.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/setup.py:150
Finding

TV Pre-Shared Key Is Stored and Transmitted in Plaintext

Content
View full analysis

Vulnerability Details

File Location: scripts/setup.py:62-66, scripts/setup.py:150-155, scripts/tv_control.py:127-128, and scripts/tv_control.py:153-160
Vulnerability Type: Insecure credential storage and plaintext network transmission
Risk Level: Medium

Vulnerable Code

The setup script writes the PSK directly into a plaintext .env file without explicitly enforcing restrictive permissions:

python
# Write .env
env_content = f"""# Sony Bravia TV — generated by setup.py
SONY_TV_IP={tv_ip}
SONY_TV_PSK={tv_psk}
SONY_TV_MAC={tv_mac}
"""
ENV_FILE.write_text(env_content)

The connection test transmits the same credential over HTTP:

python
url = f"http://{ip}/sony/system"
payload = json.dumps({"method": "getPowerStatus", "id": 1, "params": [], "version": "1.0"})
req = urllib.request.Request(url, data=payload.encode(), headers={
    "X-Auth-PSK": psk,
    "Content-Type": "application/json"
})

Normal JSON-RPC control requests also use HTTP:

python
url = f"http://{TV_IP}/sony/{endpoint}"
payload = {
    "method": method,
    "id": 1,
    "params": params or [],
    "version": version,
}
headers = {"X-Auth-PSK": TV_PSK, "Content-Type": "application/json"}

IRCC control requests use the same plaintext transport and authentication header:

python
url = f"http://{TV_IP}/sony/IRCC"
body = f'<?xml version="1.0"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:X_SendIRCC xmlns:u="urn:schemas-sony-com:service:IRCC:1"><IRCCCode>{code}</IRCCCode></u:X_SendIRCC></s:Body></s:Envelope>'
headers = {
    "X-Auth-PSK": TV_PSK,
    "Content-Type": "text/xml; charset=UTF-8",
    "SOAPACTION": '"urn:schemas-sony-com:service:IRCC:1#X_SendIRCC"',
}

Technical Analysis

Path.write_text() creates or r ...[truncated 2909 chars]

Remediation
View remediation

Remediation Suggestions

  1. Create the credential file atomically with owner-only permissions, such as mode 0600, and verify the resulting ownership and mode.
  2. Reject symbolic-link destinations and avoid truncating or replacing a file until its type and ownership have been validated.
  3. Prefer an operating-system secret store or another protected credential mechanism instead of a plaintext project-level .env file.
  4. Validate SONY_TV_IP as an IP address and, where appropriate, restrict it to expected private or explicitly approved local-network addresses.
  5. Use HTTPS with certificate validation if the television model supports it.
  6. If the device supports only HTTP, clearly document that the PSK is exposed to local-network interception and recommend a trusted, isolated IoT network.
  7. Generate and recommend a long, random PSK rather than the weak example sony1234 shown in README.md.
  8. Rotate the television PSK immediately if the .env file or local network traffic may have been exposed.
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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (15)

Tainted flow: 'url' from os.environ.get (line 142, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/tv_control.py (reported line 118)May include surrounding context.

python
}
    headers = {"X-Auth-PSK": TV_PSK, "Content-Type": "application/json"}
    try:
        resp = requests.post(url, json=payload, headers=headers, timeout=TIMEOUT)
        resp.raise_for_status()
        try:
            return resp.json()

Tainted flow: 'url' from os.environ.get (line 142, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/tv_control.py (reported line 150)May include surrounding context.

python
"SOAPACTION": '"urn:schemas-sony-com:service:IRCC:1#X_SendIRCC"',
    }
    try:
        resp = requests.post(url, data=body, headers=headers, timeout=TIMEOUT)
        resp.raise_for_status()
        print(f"OK: {code_name}")
    except requests.exceptions.Timeout:

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/setup.py (reported line 5)May include surrounding context.

python
"""Interactive setup for Sony Bravia TV skill.

Discovers the TV on the local network, tests connectivity,
and writes env vars to a .env file for tv_control.py.
"""

import json

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/tv_control.py (reported line 19)May include surrounding context.

python
"""Interactive setup for Sony Bravia TV skill.

Discovers the TV on the local network, tests connectivity,
and writes env vars to a .env file for tv_control.py.
"""

import json

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/setup.py (reported line 17)May include surrounding context.

python
from pathlib import Path

SKILL_DIR = Path(__file__).resolve().parent.parent
ENV_FILE = SKILL_DIR / ".env"

def prompt(msg, default=None):
    suffix = f" [{default}]" if default else ""

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/tv_control.py (reported line 20)May include surrounding context.

python
from pathlib import Path

SKILL_DIR = Path(__file__).resolve().parent.parent
ENV_FILE = SKILL_DIR / ".env"

def prompt(msg, default=None):
    suffix = f" [{default}]" if default else ""

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

This code path generates plaintext .env content containing SONY_TV_PSK, which is a reusable credential for controlling the TV over the local network. In the skill context this is somewhat less severe than storing high-value internet credentials, but it still enables unauthorized device control by other local users, malware, or accidental exposure via backups or commits.

Content

Scanner excerpt · scripts/setup.py (reported line 147)May include surrounding context.

python
print(f"\n  Auto-detected MAC: {auto_mac}")
    tv_mac = prompt("TV MAC address (for Wake-on-LAN, optional)", default_mac) or ""

    # Write .env
    env_content = f"""# Sony Bravia TV — generated by setup.py
SONY_TV_IP={tv_ip}
SONY_TV_PSK={tv_psk}

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
97% confidence
Finding

The skill instructs the agent to execute shell commands, use environment secrets, access local files, and communicate over the network, but it does not declare any explicit tool scope such as allowed-tools or permissions. That creates an authorization gap where the runtime may permit broader capabilities than users or platform policy expect, increasing the chance of unintended command execution against devices on the local network.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger phrases are broad, everyday utterances like "play," "pause," "go home," and power/volume commands without strong gating or disambiguation. In an assistant environment, these can be misinterpreted from unrelated conversation and cause real-world actions on a TV, including powering devices, changing inputs, or navigating menus unexpectedly.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The open-ended mapping for "open [any app name]" is especially ambiguous because many natural requests can fit that pattern even when the user is not asking to control the TV. Since the skill forwards arbitrary app names to the script for automatic search of installed apps, accidental invocation can trigger unintended application launches on a household device.

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 · scripts/setup.py (reported line 78)May include surrounding context.

python
def get_mac(ip):
    """Try to get MAC address from ARP table."""
    try:
        result = subprocess.run(["ip", "neigh", "show", ip], capture_output=True, text=True, timeout=5)
        match = re.search(r'([0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2})', result.stdout, re.I)
        if match:
            return match.group(1).upper()

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 · scripts/setup.py (reported line 85)May include surrounding context.

python
except Exception:
        pass
    try:
        result = subprocess.run(["arp", "-n", ip], capture_output=True, text=True, timeout=5)
        match = re.search(r'([0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2})', result.stdout, re.I)
        if match:
            return match.group(1).upper()

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The setup script stores the TV pre-shared key in plaintext in a .env file without an explicit warning or permission hardening. Although this is a local-network device credential rather than a cloud secret, anyone with filesystem access to the skill directory could recover the PSK and control the TV API.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/tv_control.py (reported line 118)May include surrounding context.

python
}
    headers = {"X-Auth-PSK": TV_PSK, "Content-Type": "application/json"}
    try:
        resp = requests.post(url, json=payload, headers=headers, timeout=TIMEOUT)
        resp.raise_for_status()
        try:
            return resp.json()

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The markdown instructs users to set the SONY_TV_PSK environment variable, which is a credential used to control the TV, but it does not include any caution about keeping the key private or avoiding exposure in logs, screenshots, or shared shell history. For a skill that handles credentials, a brief warning about sensitive data handling would improve user awareness.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.