T09 · Insecure Skill Coding Practices
- Location
scripts/summarize.py:544- Finding
Automatic Disclosure of Video Transcripts to an Anonymous Third-Party LLM
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This video summarizer is not clearly malicious, but it needs review because it can use browser login cookies and send transcript content to external AI services by default.
Review before installing. Use it only for public or non-sensitive videos unless you are comfortable sending transcript excerpts to configured LLM services or Pollinations. Avoid Bilibili mode unless you explicitly intend to let yt-dlp use Chrome cookies; preferably run it in an isolated environment or dedicated browser profile, remove the no-certificate-check option, and keep LLM_API_URL pointed only at a trusted endpoint.
scripts/summarize.py:544Automatic Disclosure of Video Transcripts to an Anonymous Third-Party LLM
scripts/summarize.py:160Unconditional Browser-Cookie Access with TLS Certificate Verification Disabled
scripts/summarize.py:474Unvalidated Custom LLM Endpoint Can Receive Bearer Credentials and Transcript Data
setup.sh:38Unpinned Third-Party Dependencies Are Installed and Executed
scripts/summarize.py:54Untrusted Transcript Content Is Embedded Directly into LLM Instructions
External input (network, user) flows to a code execution sink. This enables remote code execution or command injection.
url = f"https://www.youtube.com/@{channel_id}/videos"
try:
result = subprocess.run(
[
"yt-dlp",
"--flat-playlist",
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
def get_copilot_session_token(gh_token: str) -> Optional[str]:
try:
import requests
r = requests.get(
"https://api.github.com/copilot_internal/v2/token",
headers={
"Authorization": f"token {gh_token}",
The skill allows LLM_API_URL to fully control the outbound endpoint while also attaching a bearer token and sending transcript content. In an agent environment, a malicious user or wrapper can point this to an attacker-controlled server and cause credential leakage plus exfiltration of potentially sensitive transcript data.
}
if api_key:
headers["Authorization"] = f"Bearer {api_key}"
response = requests.post(
api_url,
headers=headers,
json={
The use of --cookies-from-browser chrome causes the tool to access browser-stored authentication material and hand it to a downloader, which is highly sensitive behavior. While likely intended to bypass Bilibili restrictions rather than steal credentials, this is still dangerous in a skill because it leverages ambient local secrets without strong user awareness or limitation.
.path.join(output_dir, f"bili_{video_id}_audio.mp3")
frames_dir = os.path.join(output_dir, f"bili_{video_id}_frames")
transcript_path = os.path.join(output_dir, f"bili_{video_id}_transcript.txt")
print(f"🎬 Bilibili: {video_id}", file=sys.stderr)
# Step 1: Download video
print(" 📥 Downloading video...", file=sys.stderr)
download_cmd = [
"yt-dlp",
"--cookies-from-browser", "chrome",
"--no-check-certificates",
"-f", "bestvideo[height<=720]+bestaudio/best[height<=720]",
"--merge-output-format", "mp4",
"-o", video_path,
url,
]
subprocess.run(download_cmd, check=True, timeout=300)
# Step 2: Extract audio
print(" 🎵 Extracting audio...", file=sys.stderr)
subprocess.run([
"ffmpeg", "-y", "-i", video_path,
"-vn", "-acodec", "libmp3lame", "-q:a", "2",
audio_path,
], check=True, timeout=120, capture_output=True)
# Step 3: Whisper transcription
print
Using --no-check-certificates disables TLS certificate verification for yt-dlp downloads, allowing man-in-the-middle interception or tampering of retrieved video content. In combination with browser-cookie reuse, this materially increases the risk of session misuse, content poisoning, or credential exposure on hostile networks.
download_cmd = [
"yt-dlp",
"--cookies-from-browser", "chrome",
"--no-check-certificates",
"-f", "bestvideo[height<=720]+bestaudio/best[height<=720]",
"--merge-output-format", "mp4",
"-o", video_path,
The README states the skill only supports YouTube, while the broader skill metadata says it is multi-platform and mentions Bilibili. This inconsistency can cause an agent or operator to invoke the skill with unsupported assumptions, leading to incorrect routing, unexpected failures, or accidental handling of data through unintended code paths.
The documentation includes an explicit Bilibili URL example even though the README says the skill only supports YouTube. In agent ecosystems, examples are often treated as operational guidance, so this mismatch can trigger unsupported execution paths, user confusion, or misprocessing of external content.
The README describes sending transcripts and summaries to external LLM endpoints and downstream messaging platforms, but provides no privacy, consent, retention, or data-handling warning. Video transcripts may contain personal, sensitive, copyrighted, or confidential information, so users may unknowingly exfiltrate content to third-party services.
The skill advertises capabilities that include environment access, file read/write, network, and shell execution, but it does not declare any explicit tool scope or permissions boundaries. In an agent ecosystem, this weakens policy enforcement and makes it easier for the skill to be invoked with broader privileges than users expect, especially given it downloads content, writes files, and may call external services.
The description is broad enough to trigger on generic summarization or digest requests, which can cause over-invocation of a skill that performs network access, local file writes, transcript extraction, and external summarization. That increases the chance an agent uses this skill in situations where a simpler or safer summarizer would suffice, exposing local and remote side effects unexpectedly.
The primary explanatory content begins in Chinese and the document does not indicate that users may choose their preferred language. For organizational language policy, forcing a specific language without opt-in can be a natural-language policy violation.
The skill generates summaries through LLM APIs and explicitly supports custom endpoints and anonymous Pollinations calls, but it does not clearly warn that video-derived content such as transcripts, titles, metadata, and possibly frame descriptions may be transmitted to third parties. This creates a privacy and data-handling risk, especially for non-public, sensitive, or copyrighted material.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
sudo apt install ffmpeg
pip install faster-whisper yt-dlp youtube-transcript-api innertube
The implementation performs significantly more than lightweight transcript extraction: it downloads full videos, writes media/transcript artifacts to disk, and generates frames. In an agent skill, that broader behavior increases privacy and storage exposure because users may not expect large local artifacts or retained content from a summarization request.
The script reads browser cookies from Chrome and uses environment tokens to access external services, which goes beyond ordinary transcript extraction and creates access to sensitive local credentials. In a skill context, this is especially dangerous because users may invoke summarization without realizing the tool will reach into browser state and reuse ambient secrets.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
"-o", video_path,
url,
]
subprocess.run(download_cmd, check=True, timeout=300)
# Step 2: Extract audio
print(" 🎵 Extracting audio...", file=sys.stderr)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
# Step 2: Extract audio
print(" 🎵 Extracting audio...", file=sys.stderr)
subprocess.run([
"ffmpeg", "-y", "-i", video_path,
"-vn", "-acodec", "libmp3lame", "-q:a", "2",
audio_path,
The Whisper transcription call hard-codes language="zh", which imposes a specific language/locale behavior regardless of user preference or source content. This matches the policy category for language or locale constraints without user opt-in.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
if not skip_frames:
print(f" 🖼️ Extracting keyframes (every {frame_interval}s)...", file=sys.stderr)
os.makedirs(frames_dir, exist_ok=True)
subprocess.run([
"ffmpeg", "-y", "-i", video_path,
"-vf", f"fps=1/{frame_interval}", "-q:v", "2",
os.path.join(frames_dir, "frame_%03d.jpg"),
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
url = f"https://www.youtube.com/@{channel_id}/videos"
try:
result = subprocess.run(
[
"yt-dlp",
"--flat-playlist",
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def get_video_details(video_id: str) -> Optional[Dict]:
"""Get detailed video metadata using yt-dlp"""
try:
result = subprocess.run(
[
"yt-dlp",
"--no-warnings",
The code downloads caption content from a URL obtained from remote metadata without validating the destination host or scheme. If an upstream response is malicious or compromised, this can turn the skill into a server-side request gadget that fetches attacker-chosen resources and may expose internal network reachability or be abused for unexpected outbound requests.
def _download_caption(url: str) -> Optional[str]:
try:
import requests
r = requests.get(url, timeout=15)
if r.status_code == 200 and r.text.strip():
return r.text
except Exception:
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
try:
import requests
r = requests.get(
"https://api.github.com/copilot_internal/v2/token",
headers={
"Authorization": f"token {gh_token}",
"Editor-Version": "vscode/1.95.0",
This network transmission sends transcript content and possibly authentication credentials to an endpoint that may be user/environment-controlled. In agent deployments, unrestricted outbound transmission of prompt data to arbitrary APIs is dangerous because it enables both data exfiltration and secret disclosure.
}
if api_key:
headers["Authorization"] = f"Bearer {api_key}"
response = requests.post(
api_url,
headers=headers,
json={
Transcripts are sent to external LLM endpoints without any explicit warning, approval step, or data-classification check. Video transcripts can contain private, copyrighted, regulated, or confidential information, so undisclosed transmission to third parties is a substantive privacy and compliance vulnerability in this context.
No suspicious patterns detected.