Back to skill

Security audit

Video Notes

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent video-notes tool, but it needs Review because it can access browser sessions, leave exported cookies in /tmp, install unpinned code at runtime, and generate scriptable HTML from untrusted captions.

Install only if you are comfortable running video-download tooling locally. Avoid using browser-cookie mode for private, paid, or sensitive accounts unless you understand the risk, and delete /tmp/yt-cookies-export.txt after any run. Prefer an isolated environment with pinned dependencies, and treat generated HTML from untrusted videos as potentially active content.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/extract_subtitles.py:103
Finding

Persistent Plaintext Export of Browser Session Cookies

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/extract_subtitles.py:37
Finding

Automatic Installation of an Unpinned Runtime Dependency

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
assets/note-template.html:152
Finding

Stored Script and HTML Injection Through Untrusted Subtitle Data

Content
View full analysis
const S={{SUBTITLE_JSON}}; const KF={{KEYFRAMES_JSON}}; // Render keyframes gallery (function(){ const grid=document.getElementById('kfGrid'); if(!grid||!KF||!KF.length){ const sec=document.getElementById('keyframes'); if(sec) sec.style.display='none'; return; } const vid='{{VIDEO_ID}}'; grid.innerHTML=KF.map(k=>{ const u=`https://www.youtube.com/watch?v=${vid}&t=${Math.floor(k.s)}s`; const label=(k.text||'').slice(0,80)+((k.text||'').length>80?'…':''); return `
${k.t}
${label}
`; }).join(''); })(); function rs(d,q=''){ const l=document.getElementById('sl'),c=document.getElementById('sc'); if(!d.length){l.innerHTML='
未找到匹配内容
';c.textContent='0 条';return;} const esc=s=>s.replace(/[.*+?^${}()|[\]\\]/g,'\\$&'); l.innerHTML=d.map(s=>{ let t=s.text.replace(/`${m}`);} const vid='{{VIDEO_ID}}'; const u=`https://www.youtube.com/watch?v=${vid}&t=${Math.floor(s.s)}s`; return `
${s.t}$ ...[truncated 2940 chars]
Remediation
View remediation
`, `&`, Unicode line separators, and script-closing sequences. Encoding `<` as `\u003c` prevents `` termination. 3. Prefer storing JSON in a non-executable data element and parsing its `textContent`, while still applying safe HTML-context escaping. 4. Replace `innerHTML` construction with DOM APIs: - Create elements with `document.createElement`. - Assign remote text through `textContent`. - Register click behavior with `addEventListener`. - Set validated attributes through DOM properties. 5. Implement search highlighting by splitting text into text nodes and explicit `` elements rather than generating HTML strings. 6. Validate `VIDEO_ID` against the expected platform-specific identifier format. 7. Validate timestamps as finite, non-negative numbers before constructing URLs. 8. Validate Base64 image data and avoid allowing untrusted values to select arbitrary URL schemes. 9. Add a restrictive Content Security Policy. Remove inline event handlers and inline script where practical so the policy can omit `unsafe-inline`. 10. Add regression tests using captions containing ``, HTML tags, quotes, event handlers, ampersands, and malformed Unicode. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (17)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill’s declared purpose is note generation, but the workflow also includes browser-cookie use and authenticated content access that are not transparently declared as sensitive capabilities. This mismatch is dangerous because users and policy systems may approve the skill for summarization while overlooking credential-adjacent behavior and shell-based media retrieval steps.

Content

No source excerpt is available for this finding.

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Confidence
95% confidence
Finding

The skill explicitly instructs use of --cookies-from-browser chrome and even states that cookies may be automatically exported as a fallback. Accessing browser cookies is credential-adjacent and can expose authenticated session tokens for YouTube/Bilibili accounts; if mishandled, those tokens could be abused to access private or paid content or leak user account state.

Content

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

:不加 --lang

  • YouTube / B站 中文视频:--lang zh 或 --lang zh-Hans

YouTube 认证问题(常见!):

若直接运行报错 Sign in to confirm you're not a bot 或 No subtitles found,需要传入浏览器 cookies:

bash
# 使用 Chrome cookies(推荐)
python3 ~/.claude/skills/video-notes/scripts/extract_subtitles.py <url> \
  --output /tmp/subs.json \
  --cookies-from-browser chrome

# 或使用已导出的 cookies 文件
python3 ~/.claude/skills/video-notes/scripts/extract_subtitles.py <url> \
  --output /tmp/subs.json \
  --cookies /tmp/yt-cookies.txt

脚本内置降级策略(自动执行,无需手动干预):

  1. 快速路径:--skip-download 直接获取字幕(速度最快)
  2. 降级路径:若快速路径失败,自动导出 cookies 后用 -f sb3(storyboard 格式,YouTube 始终可用)触发字幕下载,解析 VTT 格式
  3. 格式兼容:优先 VTT(支持内联时间标签),失败则回

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · scripts/extract_subtitles.py (reported line 16)May include surrounding context.

python
btitles.py <url> [--output <path>] [--lang <lang>]
                                       [--cookies-from-browser <browser>]
                                       [--cookies <cookie_file>]

Output JSON format:
    [{"t": "mm:ss", "s": <seconds_float>, "text": "<content>"}, ...]

YouTube 注意事项:
  - 若遇到 "Sign in to confirm" 或 "Requested format is not available",
    需要传入 --cookies-from-browser chrome(或 firefox/safari),
    脚本会自动先导出 cookies 文件,再以 storyboard 格式触发字幕下载。
  - 字幕格式优先尝试 VTT(与 yt-dlp storyboard 下载兼容),失败则回退 SRT。

哔哩哔哩注意事项:
  - 用 --lang zh 或 --lang zh-Hans 提取中文字幕。
  - 部分视频需要登录 cookie,用 --cookies-from-browser chrome。
  - 哔哩哔哩上传字幕(非 AI 生成)用 --write-subs 而非 --write-auto-subs,
    脚本已自动兼容处理。
"""

import sys
import re
import json
import subprocess
import temp

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README describes generating subtitles, screenshots, transcripts, and a self-contained local HTML document from video content, but it does not clearly warn users about the resulting data collection, local storage, and possible privacy/copyright implications. In a skill that processes potentially sensitive internal recordings or private/unlisted videos, this omission can lead users to expose or retain more content than they intended.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill instructs the agent to read and write local files and execute shell commands, but it declares no explicit tool scope or permission boundaries. That creates an authorization gap: the runtime may permit powerful operations without transparent least-privilege constraints, increasing the risk of unintended file access or command execution beyond the user’s expectations.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

md
slug: video-notes
version: 1.1.0
author: 2992638402-art
description: 把 YouTube / 哔哩哔哩视频变成一份精美的结构化笔记。自动提取字幕、识别关键时刻并截图、生成核心论点总结和 SVG 图表,输出带侧边导航和全文搜索的单文件 HTML 文档。适用于技术演讲、公开课、播客、产品发布会等场景。This skill should be used when a user provides a YouTube or Bilibili URL and asks to take notes, summarize a video, or create a study document from video content.
---

# Video Notes Skill

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
98% confidence
Finding

Automatically installing yt-dlp at runtime via pip is dangerous because it executes package installation logic and modifies the host environment during normal skill execution. This creates a software supply chain risk, weakens reproducibility, and the use of --break-system-packages explicitly bypasses environment protections, increasing the chance of host compromise or destabilization if package resolution is tampered with or an unsafe mirror/index is used.

Content

Scanner excerpt · scripts/capture_keyframes.py (reported line 133)May include surrounding context.

python
try:
        import yt_dlp  # noqa
    except ImportError:
        subprocess.check_call(
            [sys.executable, "-m", "pip", "install", "yt-dlp", "-q", "--break-system-packages"],
            stderr=subprocess.DEVNULL,
        )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/capture_keyframes.py (reported line 172)May include surrounding context.

python
"-vf", "scale=960:-2",  # resize to 960px wide
        out_path,
    ]
    result = subprocess.run(cmd, capture_output=True)
    return result.returncode == 0 and os.path.exists(out_path)

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Dynamically installing a package at runtime is beyond the minimum permissions and behavior expected from a note-taking/subtitle tool, especially when it modifies system packages. This creates supply-chain and environment-integrity risks, and the skill context makes it more concerning because users would not expect installation side effects from a content-processing helper.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
92% confidence
Finding

The script installs yt-dlp dynamically at runtime via pip with --break-system-packages, which modifies the host environment and executes package installation code outside the stated subtitle-extraction task. This expands the trust boundary to package indexes/network delivery and can unexpectedly alter the system, making the skill more dangerous than a normal read/process utility.

Content

Scanner excerpt · scripts/extract_subtitles.py (reported line 41)May include surrounding context.

python
try:
        import yt_dlp  # noqa
    except ImportError:
        subprocess.check_call(
            [sys.executable, "-m", "pip", "install", "yt-dlp", "-q", "--break-system-packages"],
            stderr=subprocess.DEVNULL
        )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/capture_keyframes.py (reported line 157)May include surrounding context.

python
*extra_args,
            url,
        ]
        result = subprocess.run(cmd, capture_output=True, text=True)
        for f in os.listdir(tmpdir):
            if f.endswith(f".{sub_fmt}") or f.endswith(".srt"):
                path = os.path.join(tmpdir, f)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/extract_subtitles.py (reported line 67)May include surrounding context.

python
*extra_args,
            url,
        ]
        result = subprocess.run(cmd, capture_output=True, text=True)
        for f in os.listdir(tmpdir):
            if f.endswith(f".{sub_fmt}") or f.endswith(".srt"):
                path = os.path.join(tmpdir, f)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Exporting browser cookies to a fixed file path without explicit user-facing warning or secure lifecycle handling risks disclosure of active authenticated sessions. Because this skill may be run on user machines and the cookies can grant access to YouTube/Bilibili or other browser-scoped services, the context makes credential exposure materially dangerous.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
95% confidence
Finding

This code exports browser-derived authentication cookies to a fixed path under /tmp, which can expose sensitive session material to other local processes or users depending on system configuration, race conditions, or leftover files. In the context of a skill processing untrusted inputs, handling browser cookies in a predictable shared location increases credential leakage risk beyond what is necessary for subtitle extraction.

Content

Scanner excerpt · scripts/extract_subtitles.py (reported line 106)May include surrounding context.

python
# First export cookies to a file so we don't re-authenticate per attempt
    if cookies_browser and not cookies_file:
        cookies_file = "/tmp/yt-cookies-export.txt"
        subprocess.run(
            [sys.executable, "-m", "yt_dlp",
             "--cookies-from-browser", cookies_browser,
             "--cookies", cookies_file,

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

README 全部以中文描述,并在示例触发语中仅提供中文用法,没有说明是否支持其他语言或给予用户语言选择。按自然语言策略,若技能对语言/locale 作出隐含强制要求而无用户选择,可能构成语言政策问题。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The document root sets lang="zh-CN", which hard-codes a specific language/locale for rendered output. Under the policy, forcing a locale without offering user choice or documenting a justified regional constraint is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The module docstring presents key usage guidance for YouTube and Bilibili in Chinese only, which imposes a language choice on users without opt-in. This is a natural-language policy concern because the file otherwise uses English for usage text and does not indicate that Chinese-only guidance is intentional or region-specific.

Content

No source excerpt is available for this finding.