T09 · Insecure Skill Coding Practices
- Location
play_show_via_global_search.py:84- Finding
Predictable Shared Temporary File Enables Local File Manipulation
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill broadly does what it says, but it needs review because it enables ADB-based remote control and installs/runs an unpinned third-party executable with incomplete safety guidance.
Install only if you are comfortable giving the skill ADB control of a paired Google TV device. Use it on trusted networks and hosts, disable Wireless Debugging or remove unused pairings after use, and prefer a pinned or verified yt-api version before relying on the installer.
play_show_via_global_search.py:84Predictable Shared Temporary File Enables Local File Manipulation
SKILL.md:4Mutable Third-Party Executable Installed from an Unpinned Latest Version
The documented purpose understates or misstates what the skill actually does: instead of simple casting, it appears to drive a Google TV device over ADB, invoke scrcpy, manipulate UI flows, and rely on fallback search behaviors. This mismatch is dangerous because users and enforcement systems may authorize the skill expecting low-risk media casting, while the implementation has broader remote-control capability over a paired device.
Referenced artifact was not completely inspected
- The skill CLI code lives in `google_tv_skill.py` in this folder. It uses subprocess calls to `adb`, `scrcpy`, and `yt-api`, plus an internal global-search hel
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
KEYCODE_MEDIA_PAUSE = 127
def print_pairing_instructions():
"""Display instructions for enabling wireless debugging and pairing with Chromecast."""
print("""
=== ADB Wireless Debugging & Pairing Instructions ===
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
continue
elif choice == '3':
# Show instructions
print_pairing_instructions()
continue
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
def try_prompt_new_port(ip: str, message: str) -> Tuple[Optional[str], Optional[str]]:
if not connection_refused(message):
return None, None
return prompt_for_pairing(ip)
def ensure_connected(ip: Optional[str], port: Optional[int]) -> Tuple[Optional[str], Optional[str]]:
# Returns (device_spec, error_message)
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
def try_prompt_new_port(ip: str, message: str) -> Tuple[Optional[str], Optional[str]]:
if not connection_refused(message):
return None, None
return prompt_for_pairing(ip)
def ensure_connected(ip: Optional[str], port: Optional[int]) -> Tuple[Optional[str], Optional[str]]:
# Returns (device_spec, error_message)
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
def try_prompt_new_port(ip: str, message: str) -> Tuple[Optional[str], Optional[str]]:
if not connection_refused(message):
return None, None
return prompt_for_pairing(ip)
def ensure_connected(ip: Optional[str], port: Optional[int]) -> Tuple[Optional[str], Optional[str]]:
# Returns (device_spec, error_message)
The README instructs users to enable Developer Options, USB debugging, and Wireless debugging on a network-connected consumer device, but it does not warn that leaving ADB debugging enabled can expose the device to unauthorized remote control if the network is untrusted or if a paired host is compromised. In this skill’s context, ADB is central to functionality, so the guidance is operationally necessary, but the omission of security precautions makes the documentation unsafe by encouraging a persistent high-privilege management channel without mitigation guidance.
The skill exposes meaningful capabilities through external binaries and subprocess-driven device control, including shell execution, network access to ADB endpoints, environment-variable overrides, and local file caching, but it does not declare any tool scope or permissions boundary. That omission reduces transparency and weakens policy enforcement, making it easier for an operator or platform to invoke the skill without understanding that it can connect to devices, launch apps, and write state locally.
The metadata and usage imply simple casting, but the file also implements ADB wireless pairing, persistent device caching, connection management, and media key injection. This scope expansion increases the attack surface and can mislead users into granting more powerful device-control capability than the description suggests.
The code claims constrained support for YouTube/Tubi plus a helper, but it also supports arbitrary streaming apps by passing user-provided app names into a global-search UI automation fallback. That mismatch reduces user transparency and enables broader, less predictable behavior on the target device than the skill description suggests.
The code executes a secondary helper script via uv run and passes attacker-controlled values such as show and app_name into that helper. Although this call is not shell-invoked, it expands the trust boundary to another script that may perform UI automation or unsafe processing, enabling unintended actions on the connected device if untrusted input reaches this path.
app_name,
]
try:
p = subprocess.run(cmd, timeout=180)
except subprocess.TimeoutExpired:
return False, 'Global search helper timed out after 180 seconds'
except Exception as e:
The skill executes an external yt-api binary found on PATH with user-controlled search text. Even without shell injection, trusting an arbitrary PATH-resolved executable creates a supply-chain/local execution risk: a malicious or trojaned yt-api binary would run with the skill's privileges.
"""
for bin_path in yt_api_candidates():
try:
p = subprocess.run([bin_path, 'search', query], capture_output=True, text=True, timeout=15)
out = (p.stdout or '').strip()
if p.returncode != 0:
continue
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
cmd += ['-s', device]
cmd += list(args)
try:
p = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
out = ((p.stdout or '') + (p.stderr or '')).strip()
if p.returncode != 0:
return f"[ADB ERR rc={p.returncode}] {out}"
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
cmd += ['-s', device]
cmd += list(args)
try:
p = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
out = ((p.stdout or '') + (p.stderr or '')).strip()
if p.returncode != 0:
return f"[ADB ERR rc={p.returncode}] {out}"
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
cmd += ['-s', device]
cmd += list(args)
try:
p = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
out = ((p.stdout or '') + (p.stderr or '')).strip()
if p.returncode != 0:
return f"[ADB ERR rc={p.returncode}] {out}"
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def launch_scrcpy(device):
if not SCRCPY_PATH:
return None
return subprocess.Popen(
[SCRCPY_PATH, "-s", device, "--max-size", "1024", "--always-on-top"],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
)
No suspicious patterns detected.