Back to skill

Security audit

Jellyfin Control

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly does what it says, but its Android TV ADB path can turn user-controlled input into host shell commands and its examples send sensitive tokens over plaintext HTTP.

Review before installing. Use HTTPS or a trusted encrypted tunnel for Jellyfin and Home Assistant, use least-privileged dedicated API keys/tokens, avoid admin Jellyfin credentials unless you need history or scan, and do not use the direct ADB backend until ADB_DEVICE and app IDs are validated or ADB execution is changed to argument-based process calls.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
tv.js:209
Finding

OS Command Injection Through ADB Device and Application Parameters

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
jellyfin.js:23
Finding

Sensitive Jellyfin and Home Assistant Credentials Permitted Over Plaintext HTTP

Content
View full analysis
{ const url = new URL(`/api/services/${domain}/${service}`, TV_CONFIG.haUrl); const isHttps = url.protocol === 'https:'; const lib = isHttps ? https : http; const body = JSON.stringify(data); const options = { method: 'POST', hostname: url.hostname, port: url.port || (isHttps ? 443 : 80), path: url.pathname, headers: { 'Authorization': `Bearer ${TV_CONFIG.haToken}`, 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) } }; ``` The documentation recommends plaintext URLs for both sensitive services: ```json "JF_URL": "http://192.168.1.50:8096", "JF_API_KEY": "your-jellyfin-api-key", "JF_USER": "victor", "HA_URL": "http://192.168.1.138:8123", "HA_TOKEN": "your-ha-long-lived-token" ``` ### Technical Analysis The application does not require TLS for Jellyfin or Home Assistant connections. When an `http://` URL is configured, Jellyfin ...[truncated 2376 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (29)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The description emphasizes playback and TV control, but the document also advertises history retrieval, library statistics, and library scan operations. Undeclared or under-declared administrative behaviors are dangerous because users may authorize the skill for simple media control without realizing it can access activity data or trigger state-changing server operations.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The description emphasizes playback and TV control, but the document also advertises history retrieval, library statistics, and library scan operations. Undeclared or under-declared administrative behaviors are dangerous because users may authorize the skill for simple media control without realizing it can access activity data or trigger state-changing server operations.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description emphasizes playback and TV control, but the document also advertises history retrieval, library statistics, and library scan operations. Undeclared or under-declared administrative behaviors are dangerous because users may authorize the skill for simple media control without realizing it can access activity data or trigger state-changing server operations.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 128)May include surrounding context.

md
| `TV_BACKEND`       | All       | Force backend: `homeassistant`, `webos`, `androidtv`, or `auto`       |
| `TV_PLATFORM`      | HA        | Force platform: `webos` or `androidtv` (auto-detected from entity)    |
| `HA_URL`           | HA        | Home Assistant URL, e.g. `http://192.168.1.138:8123`                  |
| `HA_TOKEN`         | HA        | HA long-lived access token (Profile → Long-Lived Access Tokens)       |
| `HA_TV_ENTITY`     | HA        | Entity ID of your TV, e.g. `media_player.lg_webos_tv_oled48c34la`     |
| `TV_IP`            | WebOS     | LG TV IP address for direct WebOS SSAP connection                     |
| `TV_CLIENT_KEY`    | WebOS     | Pairing key (printed on first connection — save it!)                  |

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 128)May include surrounding context.

md
| `TV_BACKEND`       | All       | Force backend: `homeassistant`, `webos`, `androidtv`, or `auto`       |
| `TV_PLATFORM`      | HA        | Force platform: `webos` or `androidtv` (auto-detected from entity)    |
| `HA_URL`           | HA        | Home Assistant URL, e.g. `http://192.168.1.138:8123`                  |
| `HA_TOKEN`         | HA        | HA long-lived access token (Profile → Long-Lived Access Tokens)       |
| `HA_TV_ENTITY`     | HA        | Entity ID of your TV, e.g. `media_player.lg_webos_tv_oled48c34la`     |
| `TV_IP`            | WebOS     | LG TV IP address for direct WebOS SSAP connection                     |
| `TV_CLIENT_KEY`    | WebOS     | Pairing key (printed on first connection — save it!)                  |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 236)May include surrounding context.

md
- `cli.js` — User-friendly CLI with all commands

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · README.md (reported line 27)May include surrounding context.

npm install ws

If using direct ADB backend (Android TV / Fire TV):

sudo apt install adb # Debian/Ubuntu

or: brew install android-platform-tools # macOS

text

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILL.md (reported line 107)May include surrounding context.

npm install ws

If using direct ADB backend (Android TV / Fire TV):

sudo apt install adb # Debian/Ubuntu

or: brew install android-platform-tools # macOS

text

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill declares required environment variables, including sensitive API keys and tokens, but does not declare an explicit tool scope or permission boundary. That omission makes the skill's access expectations less transparent and weakens reviewability, increasing the chance that a caller grants broader capabilities than intended.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill metadata describes playback/session/TV control, but the CLI also exposes a library administration action via scan. Hidden or undocumented administrative capabilities expand the effective permission surface and can surprise users or orchestrators into invoking a more impactful action than expected. In this context, triggering a library scan is not destructive in the classic sense, but it can consume server resources and perform an administrative operation outside the declared scope.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill exposes admin-only capabilities to read activity history and trigger a library refresh, which exceed the stated playback/control scope. In an agent context, unnecessary privileged actions increase attack surface and can enable privacy-invasive access to viewing history or unauthorized administrative operations if the skill is invoked with elevated Jellyfin credentials.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This file includes server-administration behavior not justified by a media playback controller, namely reading system activity logs and initiating library scans. Even though Jellyfin enforces privileges server-side, embedding these actions in a broadly usable playback skill creates scope creep and raises the risk of misuse when an admin API key or admin password is configured.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

The manifest describes media-server and TV control, but does not indicate that the skill will execute local system binaries via child_process. Running adb through execSync gives the skill host-level command execution dependencies that are not apparent from the stated purpose.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

This method invokes Home Assistant's media_player.turn_off, which can immediately power off the user's TV. The code emits only a success log after execution and does not present any warning or confirmation before performing the irreversible/disruptive action.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The manifest describes controlling Jellyfin playback flow and TV power/apps, but this file also implements listing installed applications/packages on the TV through Home Assistant. Enumerating installed apps is a broader device-inspection capability than the stated one-command Jellyfin control workflow and is not mentioned in the manifest description.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The manifest frames the skill as controlling Jellyfin media server and TV, but the implementation provides a general-purpose ADB command executor used for package listing, connection management, key events, and app launching. This introduces a broader device-control surface than the manifest explicitly claims, even though some uses support TV control.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · tv.js (reported line 233)May include surrounding context.

js
throw new Error(
            'adb is not installed or not in PATH.\n' +
            'Install it:\n' +
            '  • Debian/Ubuntu: sudo apt install adb\n' +
            '  • macOS:         brew install android-platform-tools\n' +
            '  • Or use TV_BACKEND=homeassistant instead'
        );

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The Android TV turnOff method uses ADB to send KEYCODE_SLEEP, changing the state of the target device in a potentially disruptive way. Although the code logs success afterward, it does not provide any prior user disclosure or confirmation that the operation will immediately put the TV to sleep.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The turnOff method for the WebOS backend sends system/turnOff, which is a destructive/disruptive operation affecting device state. Unlike pairing or wake operations, there is no user-facing warning, confirmation prompt, or cautionary comment around this shutdown behavior in the code shown.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

This markdown file describes commands that power on/off a TV, launch apps, and send playback/volume controls, which can affect system state and connected devices. While the usage is explicit, there is no direct warning in the usage section that these commands will immediately control the user's TV and alter playback/device state.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest does not disclose that the skill can inspect user activity history, yet the CLI provides a history command that reveals viewing activity. This is a scope/consent issue: even if the underlying API legitimately supports it, exposing user-behavior data without clear declaration can lead to privacy surprises and misuse in multi-user environments.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The CLI exposes a stats command for library analytics, but this capability is not mentioned in the manifest. While lower risk than direct control or admin actions, it still expands data exposure beyond the documented behavior and may leak information about the media library's size and composition.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The scan command immediately triggers a library refresh without warning, confirmation, or friction. Because library scans can be resource-intensive and may affect server responsiveness, executing them as a one-step command increases the chance of accidental or repeated administrative impact, especially when invoked through automation or an agent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

This code reads a password from the JF_PASS environment variable and sends it to /Users/AuthenticateByName, but the only user-facing log messages about login are commented out. For code files, credential use and network transmission of sensitive data should have some visible disclosure unless clearly surfaced elsewhere; in this file, that disclosure is absent in the active execution path.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
93% confidence
Finding

The axios dependency is specified with a caret range, which allows newer minor/patch versions to be installed over time. This reduces build reproducibility and can expose the skill to accidental supply-chain risk or unexpected vulnerable releases, though by itself it is a hardening issue rather than an immediate exploitable flaw in this manifest.

Content

Scanner excerpt · package.json (reported line 13)May include surrounding context.

json
"author": "Titunito",
  "license": "ISC",
  "dependencies": {
    "axios": "^1.13.5",
    "fuse.js": "^7.1.0",
    "yargs": "^18.0.0"
  },

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
tv.js:213

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
jellyfin.js:7