T09 · Insecure Skill Coding Practices
- Location
scripts/yt_utils.py:1126- Finding
Unrestricted LLM Endpoint Can Exfiltrate API Credentials and Transcript Content
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This YouTube archiver is mostly coherent, but it needs review because it handles browser-authenticated YouTube data, API keys, external AI calls, and has under-scoped endpoint and file-write behavior.
Install only if you are comfortable giving the skill access to YouTube session cookies or a cookies.txt file and sending transcripts to the configured AI provider. Prefer dry runs, review .config.json carefully, avoid custom base_url values unless you fully trust the endpoint, use least-privilege API keys, and keep playlist names as simple folder labels without path characters.
scripts/yt_utils.py:1126Unrestricted LLM Endpoint Can Exfiltrate API Credentials and Transcript Content
scripts/yt_utils.py:1690Playlist Name Path Traversal Allows Writes Outside the Archive Directory
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).
use.
3. **macOS:** The terminal app (Terminal, iTerm, etc.) needs **Full Disk Access** in System Settings > Privacy & Security to read Chrome's cookie database. Without it, `yt-dlp` silently gets no cookies and private playlists appear empty.
4. **macOS (Chrome specifically):** Chrome may also prompt "allow Terminal to access data from other apps" — click Allow.
5. Test directly:
- `yt-dlp --cookies-from-browser chrome --flat-playlist "https://www.youtube.com/playlist?list=LL"`
6. If browser cookie extraction still fails, export cookies via a browser extension (e.g. "Get cookies.txt LOCALLY") and set `cookies_file` in config.
---
## Rate limiting / transient network errors
### Symptoms
- HTTP 429
- Timeouts
- intermittent 5xx errors
### Fixes
1. Run in smaller batches: `yt-enrich.py --limit 5`.
2. Retry later; built-in backoff already retries transient failures.
3. Prefer authenticated requests (`browser`/`cookies_file`) over anonymous requests.
---
## Missing transcripts
#
File contents flow to a network sink. This may indicate data exfiltration of sensitive files.
for attempt in range(1, attempts + 1):
req = urllib.request.Request(url, data=data, headers=headers)
try:
with urllib.request.urlopen(req, timeout=timeout_s) as response:
raw = response.read().decode("utf-8", errors="replace")
if not raw.strip():
return {}
The README explicitly states that the skill generates AI summaries and tags using external LLM providers, which implies transcripts and other video content may be transmitted off-device. Without a clear privacy warning and consent language, users may unknowingly send copyrighted, private, or sensitive viewing content to third-party services.
The activation phrase "Archive my YouTube playlists" is broad enough that an agent could initiate actions affecting multiple playlists, including private or sensitive ones, without clearly bounded scope or an explicit confirmation flow described in the README. In an agent setting, vague triggers increase the risk of over-collection and unintended access to personal data.
The README mentions platform-specific cookie access behavior, including Full Disk Access on macOS and reading browser cookies for private playlists, but does not present this as a clear security warning. Access to browser cookies is highly sensitive because it can expose authenticated session material and expands the skill's effective privileges over the local system.
The skill documents capabilities that involve shell execution, network access, reading browser cookies, file writes, and use of environment-based API keys, but it declares no explicit tool scope or permission boundaries. That creates a real security issue because an agent may invoke the skill with broader-than-necessary privileges, increasing the blast radius for data exposure, cookie theft, arbitrary command execution, or unintended filesystem modification.
The invocation language is broad enough to match common user requests like importing, syncing, enriching notes, automation, or batch processing, which can cause the skill to trigger in situations where the user did not intend browser-cookie access, network retrieval, or local file writes. In this context, overbroad routing is risky because the skill performs sensitive actions against local files and authenticated YouTube data, so accidental invocation can lead to privacy and integrity issues.
The skill instructs use of browser cookie extraction and API-key configuration without an explicit user-facing warning about the sensitivity of those credentials and the risks of local token exposure. This is dangerous because browser cookies for signed-in YouTube sessions can grant access to private playlists or account data, and poorly handled API keys can be leaked through logs, config files, or misconfigured environments.
This documentation instructs users to configure third-party AI providers and implies transcript summarization/tagging workflows, but it does not warn that video transcripts, metadata, or derived notes may be transmitted to external services. In a YouTube archiving skill, that omission can cause unintentional disclosure of private Watch Later/Liked content, transcript text, or other sensitive viewing data to remote providers.
The inline comment says os.kill(pid, 0) on Windows 'actually terminates the process', which contradicts what signal 0 is intended to do and what the code itself avoids by switching to OpenProcess. This is an active documentation contradiction about a process-management side effect, not merely an omission.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def run_command(cmd, timeout=120):
try:
completed = subprocess.run(
cmd,
capture_output=True,
text=True,
The helper functions transmit prompts and transcript-derived content to configurable external AI endpoints, potentially alongside API credentials, without any built-in warning, confirmation, or endpoint restrictions. Because base_url is configurable, a user or downstream component could direct sensitive content to arbitrary servers, increasing privacy and exfiltration risk.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
def _call_anthropic(prompt, provider_cfg, timeout_s, temperature, max_tokens):
model = str(provider_cfg.get("model", "")).strip()
base_url = str(provider_cfg.get("base_url", "")).strip() or "https://api.anthropic.com/v1/messages"
api_key_env = str(provider_cfg.get("api_key_env", "")).strip()
api_key = os.environ.get(api_key_env, "") if api_key_env else ""
if not api_key:
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
timeout_s=timeout_s,
temperature=temperature,
max_tokens=max_tokens,
default_url="https://api.openai.com/v1/chat/completions",
auth_header=True,
)
elif provider == "openrouter":
This code sends transcript content to external LLM providers for summarization and tagging, which can expose sensitive or private video content to third-party services. In the context of an archiving skill that may process private playlists such as Watch Later or Liked Videos, users may not realize their viewing data and transcripts are being transmitted off-device.
This utility runs external commands via subprocess.run and is later used for yt-dlp and summarize invocations. Although subprocess execution is central to the implementation, this file itself provides no visible user disclosure such as a print/log message or inline warning about executing external binaries.
No suspicious patterns detected.