Back to skill

Security audit

Streaming Buddy

Security checks for vulnerabilities and agentic risk

Overview

This streaming assistant mostly does what it claims, but it deserves review because it stores a TMDB API key and personal viewing profile locally while sending viewing-related requests to TMDB.

Install only if you are comfortable keeping a TMDB API key and your watch history/preferences in the workspace. Use explicit /stream commands, choose your own region/language, and consider storing secrets outside shared workspaces or rotating the TMDB key if it was already placed in config.json.

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

Warning
Location
scripts/handler.sh:35
Finding

TMDB API Key Stored in Plaintext and Exposed Through Process Arguments

Content
View full analysis
/dev/null || echo "") ``` The key is then embedded in URLs passed to `curl`: ```bash local url="${TMDB_BASE}/search/${type}?api_key=${TMDB_API_KEY}&query=${encoded_query}&language=de-DE®ion=${REGION}" local result result=$(curl -s --max-time 10 "$url" 2>/dev/null || echo '{"results":[]}') ``` ```bash local url="${TMDB_BASE}/${type}/${id}?api_key=${TMDB_API_KEY}&language=de-DE&append_to_response=credits,keywords,watch/providers" local result result=$(curl -s --max-time 10 "$url" 2>/dev/null || echo '{}') ``` ```bash local url="${TMDB_BASE}/discover/${type}?api_key=${TMDB_API_KEY}&language=de-DE&watch_region=${REGION}&sort_by=${sort}&vote_count.gte=50" [[ -n "$providers" ]] && url="${url}&with_watch_providers=${providers// /%20}" [[ -n "$genres" ]] && url="${url}&with_genres=${genres// /%20}" local result result=$(curl -s --max-time 10 "$url" 2>/dev/null || echo '{"results":[]}') ``` ### Technical Analysis The TMDB API key is treated as ...[truncated 2155 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/handler.sh:532
Finding

Untrusted Values Are Interpolated Directly into jq Programs and JSON Responses

Content
View full analysis
200 then "..." else "" end)), poster: (if .poster_path then "https://image.tmdb.org/t/p/w200" + .poster_path else null end) }] }' ;; ``` Service names are concatenated into JSON text: ```bash echo '{"status":"ok","message":"Service added","service":"'"$service"'"}' ``` ```bash echo '{"status":"ok","message":"Service removed","service":"'"$service"'"}' ``` A title obtained from the remote API is also concatenated into JSON text: ```bash echo '{"status":"ok","message":"Added to watchlist","title":"'"$title"'"}' ``` The command name is concatenated into an error response: ```bash echo '{"status":"error","message":"Unknown command: '"$CMD"'. Use help for available commands."}' ``` ### Technical Analysis Shell quoting prevents these values from being interpreted as separate shell commands, so the identified code does not directly provide shell command execution. However, it does not safely encode the values for their destination formats. In the search command, the user-controlled query becomes part of the jq prog ...[truncated 2285 chars]
Remediation
View remediation
200 then "..." else "" end)), poster: (if .poster_path then "https://image.tmdb.org/t/p/w200" + .poster_path else null end) } ] }' ``` 2. Generate service responses with jq rather than text concatenation: ```bash jq -n --arg service "$service" '{ status: "ok", message: "Service added", service: $service }' ``` 3. Generate API-derived title responses safely: ```bash jq -n --arg title "$title" '{ status: "ok", message: "Added to watchlist", title: $title }' ``` 4. Generate unknown-command errors using the same safe pattern: ```bash jq -n --arg command "$CMD" '{ status: "error", message: ("Unknown command: " + $command + ". Use help for available commands.") }' ``` 5. Validate identifiers and enumerated values before use. For example, restrict content type to `movie` or `tv`, and restrict service names to the documented supported-service list. 6. Add regression tests using quotes, backslashes, newlines, Unicode, and jq metacharacters in all user-controlled fields. Verify that every command always emits valid JSON. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (13)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill advertises shell-based handler usage and required binaries but does not declare any explicit tool scope or allowed-tools boundary. That creates an authorization gap where the runtime may permit broader shell execution than users or platform policy expect, increasing the blast radius if downstream command handling is unsafe.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger text is broad enough to match ordinary conversation about movies, streaming services, or recommendations, which can cause the skill to activate unintentionally. Because the skill stores history and preferences, accidental invocation can lead to collection, profiling, or modification of persistent user data without a clear deliberate action.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill prominently describes tracking watch habits and learning user taste, and the data files section confirms persistent storage of profile, history, services, and preferences, but it does not provide an explicit privacy warning or consent mechanism. This is dangerous because users may unknowingly reveal sensitive preference data and have long-lived profiling applied to future interactions.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The reference uses language=de-DE in endpoint examples, which forces a specific locale in the skill guidance. Under the policy rule, locale constraints should be user-selectable or clearly justified as region-specific; this file provides neither justification nor opt-in choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The discover example includes language=de-DE and watch_region=DE, which imposes a specific language and region in natural-language/API guidance. Because the file does not explain that the skill is Germany-only or offer alternatives, this is a locale policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The default configuration sets region DE and language de-DE, and later logic coerces any unsupported language back to de. This imposes a locale preference by default rather than offering a neutral choice or explicit opt-in.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

The skill depends on an external third-party API and transmits user-driven content off-box, which creates a real data exposure boundary. In this skill context, searches, watch interests, and recommendation activity can reveal personal habits and preferences, making the external transmission more sensitive than a generic metadata lookup.

Content

Scanner excerpt · scripts/handler.sh (reported line 67)May include surrounding context.

sh
[[ "$LANG" != "de" && "$LANG" != "en" ]] && LANG="de"
REGION=$(jq -r '.region // "DE"' "$CONFIG" 2>/dev/null)

TMDB_BASE="https://api.themoviedb.org/3"

# ============================================
# TMDB API Functions

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script sends user-provided search terms and inferred viewing-interest context to TMDB over the network without any user-facing disclosure or consent flow. In a personal-preference skill, this can expose sensitive behavioral data and expectation-mismatched sharing, even if the destination is a legitimate API.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

TMDB search requests always use language=de-DE, even though the script reads a language setting and exposes English responses elsewhere. This creates a locale-policy inconsistency by forcing German content retrieval without user opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The details endpoint uses language=de-DE, and discovery requests later also hardcode German language while defaulting region to DE. This continues the pattern of forcing a locale/region rather than offering or honoring explicit user selection.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The provided configuration example hard-codes region: "DE" and language: "de-DE", which may steer deployments toward a specific locale by default. While a later section notes language can be configured, the setup instructions themselves present a single locale-specific default without explaining that users should choose their own region and language.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The document instructs readers to set the user's region in services.json and gives a fixed example of "DE" plus a list of supported regions, but it does not say the region should be chosen based on the user's preference or inferred locale. This can create a locale-policy issue because content availability results depend on region and the file does not present the setting as an explicit user choice or a region-specific tool constraint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The handler loads tmdbApiKey from config.json, which is credential material, but the script provides no user-facing notice about storing or using that secret. The existing comments are implementation-oriented and do not disclose credential access/usage to the user.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.