Back to skill

Security audit

video-transcript

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a video subtitle extractor, but it needs review because it saves transcripts persistently and can accidentally output an unrelated prior transcript.

Install only if you are comfortable with the skill making network requests through `yt-dlp` and saving transcript files under your home directory. Treat it as a subtitle downloader, not a translator. Clear or isolate the transcript output directory between sensitive requests, and prefer a pinned `yt-dlp` version or a sandboxed environment.

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 (2)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:50
Finding
Unpinned Third-Party Dependency Installation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 50–54 **Vulnerability Type**: Unpinned and integrity-unverified package installation **Risk Level**: Medium ### Vulnerable Code ```markdown ## 依赖 ```bash pip install yt-dlp ``` ``` ### Technical Analysis The installation instructions direct users to install the latest version of `yt-dlp` without a fixed version, lock file, package hash, or other integrity control. Consequently, the code installed by this command can change after the Skill has been reviewed. Although `yt-dlp` is a legitimate package and there is no evidence that the project intentionally requests a malicious dependency, installing mutable third-party content without version or integrity constraints creates a supply-chain exposure. A compromised package release, compromised package repository, dependency takeover, or incompatible future release could introduce arbitrary behavior that is not represented in the audited project. Python package installation and subsequent package execution occur with the privileges of the user running the commands. ### Attack Path 1. A user follows the dependency installation instructions in `SKILL.md`. 2. `pip` resolves the current package release and its dependencies from its configured package index. 3. No project-controlled version or cryptographic hash is used to verify that the resolved artifacts match reviewed versions. 4. If the resolved package or one of its dependencies has been compromised, malicious code may execute during installation or when `yt-dlp` is subsequently invoked. 5. That code executes with the privileges and filesystem access of the user running the Skill. ### Impact Assessment Successful exploitation could allow arbitrary code execution under the installing user's account. The resulting access could include reading or modifying user-accessible files, accessing environment variables and credentials available to that account, and making network connections. Thi ...[truncated 105 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin `yt-dlp` to a specific version that has been reviewed and tested. 2. Maintain dependencies in a lock or requirements file with cryptographic hashes. 3. Install packages with hash enforcement, for example: ```bash python -m pip install --require-hashes -r requirements.txt ``` 4. Review and update pinned versions through a controlled dependency-update process. 5. Run the Skill in an isolated virtual environment or container with only the filesystem and network permissions required for transcript retrieval. 6. Where practical, verify package provenance and retain a known-good artifact in a trusted internal package repository. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
transcript.py:110
Finding
Cross-Request Transcript Disclosure Through Shared Output Directory<![CDATA[ ## Vulnerability Details **File Location**: `transcript.py`, lines 110–130 **Vulnerability Type**: Unsafe shared workspace and non-request-specific file selection **Risk Level**: Medium ### Vulnerable Code ```python # 下载字幕 output_dir = Path.home() / '.openclaw' / 'workspace' / 'video-transcripts' output_dir.mkdir(parents=True, exist_ok=True) if not download_subtitle(clean_url, str(output_dir)): print("\n提示:视频可能没有内置字幕") sys.exit(1) # 查找并转换 SRT 文件 srt_files = find_srt_files(output_dir) if not srt_files: print("错误:未找到字幕文件") sys.exit(1) # 处理最新的 SRT 文件 srt_file = max(srt_files, key=lambda f: f.stat().st_mtime) with open(srt_file, 'r', encoding='utf-8') as f: srt_content = f.read() text_content = srt_to_text(srt_content) ``` The file-discovery helper used by this code scans every SRT file in the shared directory: ```python def find_srt_files(output_dir): """查找目录中的 SRT 文件""" return list(Path(output_dir).glob('*.srt')) ``` ### Technical Analysis All invocations write to the same persistent directory under the user's home directory. After `yt-dlp` returns successfully, the code does not identify which files were generated for the current request. Instead, it scans every SRT file in the shared directory and selects whichever one has the newest modification time. A successful `yt-dlp` exit status does not establish that a new, request-specific SRT file is the newest file in that directory. Existing files, concurrently generated files, or externally placed SRT files can therefore be selected. The selected content is converted, saved to a text file, and printed as though it belongs to the requested video. This creates both a confidentiality problem and an output-integrity problem. The persistent directory also lacks per-invocation isolation, making concurrent executions unsafe. ### Attack Path 1. A transcript from a previous invocation remains in `~/.openclaw/workspace/video-transcripts`, or another process places an SRT ...[truncated 1390 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create a unique private directory for every invocation, preferably with `tempfile.TemporaryDirectory()`: ```python import tempfile with tempfile.TemporaryDirectory(prefix="video-transcript-") as output_dir: if not download_subtitle(clean_url, output_dir): sys.exit(1) srt_files = list(Path(output_dir).glob("*.srt")) # Validate and process files created only for this invocation. ``` 2. Do not select a file solely by global modification time. Capture the exact output paths produced by `yt-dlp`, use a request-specific output template, or compare the directory contents before and after execution. 3. Include the normalized video ID in a sanitized, request-specific output path and verify that the selected file matches that identifier. 4. Reject symbolic links and confirm that the resolved file remains inside the invocation-specific directory before reading it. 5. Use restrictive directory and file permissions so other users cannot insert or replace transcript files. 6. Clean up temporary subtitle files after processing unless persistent storage is explicitly required. 7. If persistent output is needed, move the validated result into a dedicated per-video destination only after successful processing. 8. Add concurrency tests and tests covering stale files, missing subtitles, multiple subtitle languages, and externally created newer SRT files. ]]>
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
声明的核心能力是将视频链接转成文字讲稿,并对非中文视频提供原文+中文翻译。代码的实际行为是:解析 YouTube/Bilibili 链接,调用 yt-dlp 获取视频信息并下载已有或自动生成字幕,随后将 SRT 去时间轴转成纯文本保存与输出。这与“提取字幕生成文字稿”基本相关,但存在重要差异:首先,代码完全没有任何翻译逻辑,因此“非中文视频提供中文翻译”这一声明明显未兑现;其次,支持的平台在代码中仅限 YouTube 和 Bilibili,未体现更广泛的平台支持;再次,代码本质上依赖目标平台已有字幕或自动字幕,若无字幕则失败,因此它更准确地说是“下载并清洗字幕”,而不是通用的视频转文字转录工具。未发现与声明无关的明显额外敏感能力,但上述能力落差已构成描述与行为不一致。

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill declares no explicit tool scope even though its documented workflow requires shell access and likely file operations via yt-dlp. Without a permissions or allowed-tools boundary, an agent may invoke broader capabilities than users expect, increasing the chance of unintended command execution or filesystem access if the skill is later implemented loosely.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The activation criteria are broad enough that the skill may trigger on routine conversation containing a video link or general transcript request, causing unnecessary tool use or network access without clear user intent. Over-broad triggering increases the attack surface for prompt-injection content embedded in linked pages or subtitles and can lead to surprise actions.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
Forcing Chinese translation/output for non-Chinese videos without user opt-in can cause unintended disclosure or transformation of user-requested content and may violate user expectations around fidelity, language preference, or data minimization. While not a severe exploit, it is a policy and consent issue that can lead to unnecessary processing of third-party content.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The workflow explicitly mandates translation into Chinese for non-Chinese content, which hardcodes extra processing without consent or user choice. This expands data handling beyond the minimum needed to satisfy a transcript request and may create compliance or expectation issues, especially for sensitive or copyrighted material.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The title, description, usage messages, status output, and prompts are all hard-coded in Chinese, indicating the skill is intended to operate only in that language. The file does not offer any language selection or explain that it is a region- or locale-specific tool, which matches the language/locale policy concern for natural-language behavior.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The manifest says non-Chinese videos should provide both the original text and a Chinese translation. In this file, the workflow fetches subtitle files, strips SRT timing metadata, saves plaintext, and prints the original transcript only; there is no language detection, translation API call, or bilingual output generation.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
]
    
    print(f"正在下载字幕...")
    result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
    
    if result.returncode == 0:
        print("✓ 字幕下载成功")
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"""获取视频信息"""
    cmd = ['yt-dlp', '--dump-json', '--no-download', url]
    try:
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
        if result.returncode == 0:
            data = json.loads(result.stdout)
            return {
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Static analysis

No suspicious patterns detected.