Back to skill

Security audit

Video Subtitle Extractor

Security checks for vulnerabilities and agentic risk

Overview

This skill appears purpose-built for video transcription, but it asks for broad install, download, browser-cookie, and persistent storage behaviors that need review before use.

Install only if you are comfortable with the skill downloading media, installing system and Python dependencies, downloading ASR models, and keeping media/transcripts on disk. Avoid browser-cookie workflows unless you trust the machine and toolchain, and prefer a dedicated output directory you can delete after use.

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

T08 · Insecure Dependencies

Warning
Location
scripts/install_deps.py:91
Finding
Unpinned Third-Party Dependencies Are Installed and Executed## Vulnerability Details **File Location**: `scripts/install_deps.py:91-123`; related installation instructions appear in `SKILL.md:55-59, 109, 121, 264-265` and `scripts/transcribe.py:517-520` **Vulnerability Type**: Unpinned dependency installation and software supply-chain exposure **Risk Level**: Medium ### Vulnerable Code ```python def install_yt_dlp(): """Install yt-dlp via pip.""" try: import yt_dlp print('[OK] yt-dlp already installed') return True except ImportError: pass print('[INSTALL] yt-dlp...') return run([sys.executable, '-m', 'pip', 'install', 'yt-dlp', '--user'], check=False) def install_whisper(mode='openai'): """Install speech-to-text engine (openai-whisper or faster-whisper).""" if mode == 'faster': try: import faster_whisper print('[OK] faster-whisper already installed') return True except ImportError: pass print('[INSTALL] faster-whisper...') return run([sys.executable, '-m', 'pip', 'install', 'faster-whisper', '--user'], check=False) else: try: import whisper print('[OK] openai-whisper already installed') return True except ImportError: pass print('[INSTALL] openai-whisper...') return run([sys.executable, '-m', 'pip', 'install', 'openai-whisper', '--user'], check=False) ``` The documentation also directs users to install other unpinned packages: ```markdown python scripts/install_deps.py pip install funasr modelscope pip install pywhispercpp ``` ### Technical Analysis The dependency installer invokes pip using package names without reviewed version constraints, a lock file, or cryptographic hashes. Pip therefore resolves whichever compatible releases and transitive dependencies are available from the configured package ind ...[truncated 2285 chars]
Remediation
## Remediation Suggestions 1. Pin every direct dependency to a reviewed version rather than installing unconstrained package names. 2. Generate a lock file that includes all transitive dependencies for each supported platform and Python version. 3. Record cryptographic hashes for approved distributions and install with `pip --require-hashes`. 4. Use an explicit trusted package index and disable unintended fallback indexes where feasible. 5. Separate optional ASR backends into individually reviewed dependency groups so users install only the backend they need. 6. Prefer prebuilt, verified wheels and prevent unreviewed source builds in production installation workflows. 7. Add automated dependency scanning and update review procedures before changing locked versions. 8. Update `SKILL.md` and `scripts/transcribe.py` so every installation example references the same locked requirements rather than direct unpinned `pip install` commands. 9. Keep dependency installation separate from normal Skill execution and clearly require user confirmation before installing or updating software. 10. Document model artifact sources and, where supported, verify downloaded model files against published checksums or signed manifests.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (20)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The documented behavior claims broad end-to-end capabilities including downloading from video sites, dependency installation, model download, and LLM calibration, while the analyzed implementation apparently lacks those controls or behaviors. This mismatch is dangerous because operators may trust the skill to handle network access, installation, persistence, and post-processing safely when it actually behaves differently, undermining review, consent, and security expectations.

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

High
Category
YARA Match
Content
20p | Good balance for local storage |
| `480` | ≤480p | Minimum acceptable for reference |
| `360` | ≤360p | Extremely small files |
| *raw string* | Direct yt-dlp format selector | Full flexibility |

> **⚠️ B站 note**: Without login cookies, B站 caps at 480p. 720p+ requires `--cookies-from-browser`.

**If download fails**: the video may require cookies. Try:
```bash
yt-dlp --cookies-from-browser chrome <url>
```

### Step 2: ASR Transcription (Multi-Backend)

Run `scripts/transcribe.py <audio> --backend <engine> --model <size> --language <lang>`.

Three backends, auto-selected by default (priority: SenseVoice → whisper.cpp → openai-whisper):

### 🥇 SenseVoice Small (default for Chinese)

| Property | Value |
|----------|-------|
| RAM | ~1.5GB |
| Disk | ~234MB |
| Speed | 20× realtime (CPU) |
| Chinese accuracy | ~96% 🏆 |
| Model source | ModelScope (auto-download, no VPN needed) |
| Install | `pip install funasr modelscope` |

> **
Confidence
75% confidence
Finding
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
if isinstance(cmd, list):
            subprocess.run(cmd, check=check, capture_output=False)
        else:
            subprocess.run(cmd, shell=True, check=check, capture_output=False)
        return True
    except subprocess.CalledProcessError:
        return False
Confidence
94% confidence
Finding
Using subprocess.run(..., shell=True) in an installer skill increases the risk of command injection or unintended command execution, especially because the skill performs package installation and may run with elevated privileges on Linux via sudo. The skill context makes this more dangerous: it is explicitly designed to auto-install dependencies across platforms, so misuse could directly alter the host system rather than only affect local application state.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill advertises and documents shell execution, environment access, and file read/write behavior but does not declare any explicit tool scope or permissions boundary. In an agent ecosystem, this makes the skill's operational authority opaque and can lead to over-broad execution, unsafe invocation, or bypass of least-privilege controls.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The documentation instructs users to use browser-cookie extraction for authenticated downloads without a clear warning about the sensitivity of those cookies. Browser cookies can grant account access and may expose session tokens to local tools, logs, or downstream processes, so recommending this flow without prominent safeguards materially increases credential and privacy risk.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill explicitly states that downloaded media, transcripts, and metadata persist on disk, but it does not present this as a prominent privacy and data-retention warning. Persisting user-requested media and generated transcripts can expose sensitive content, create unexpected retention, and increase the blast radius if the host is shared or later compromised.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The guide states to 'Always convert' traditional Chinese output to simplified Chinese, which imposes a specific locale/script policy on all applicable content. This is a natural-language policy concern because it removes user choice and does not document any opt-in, exception, or region-specific justification.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The script automatically converts traditional Chinese text to simplified Chinese during calibration, which imposes a language/locale transformation on user content by default. Although a '--no-tradsimp' flag exists, the default behavior still applies the locale-specific conversion unless the user explicitly opts out.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The skill manifest centers on subtitle extraction and audio-to-text transcription, with yt-dlp used to obtain audio for ASR. This file also provides a separate `download_video` path that downloads and merges full MP4 video streams, which is broader than the stated subtitle/audio-extraction purpose and not presented as a necessary implementation detail for transcription.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
print()

    try:
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=600)

        dest = None
        for line in result.stdout.splitlines():
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
print()

    try:
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
        combined_output = (result.stdout or '') + (result.stderr or '')

        # First try to find the output file from the output
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The command-line interface exposes `--save-video` and `--video-quality`, making full video acquisition a user-facing feature rather than an internal helper. That behavior exceeds the manifest's described role of extracting subtitles/transcribing audio from videos.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"""Run a shell command and return success."""
    try:
        if isinstance(cmd, list):
            subprocess.run(cmd, check=check, capture_output=False)
        else:
            subprocess.run(cmd, shell=True, check=check, capture_output=False)
        return True
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
if isinstance(cmd, list):
            subprocess.run(cmd, check=check, capture_output=False)
        else:
            subprocess.run(cmd, shell=True, check=check, capture_output=False)
        return True
    except subprocess.CalledProcessError:
        return False
Confidence
92% confidence
Finding
This branch executes string commands with shell=True, which allows shell parsing and command chaining if the command string is ever influenced by untrusted input. In this script, the current callers appear mostly hardcoded, but the helper is generic and already accepts arbitrary cmd values, making it an unsafe primitive for an agent skill that installs software and may evolve to consume external parameters.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The pipeline function defaults `language='zh'`, which imposes a specific locale by default rather than detecting or asking for the user's preferred language. This matches the policy category for language/locale constraints because the file does not justify the restriction as region-specific or require explicit opt-in.

Natural-Language Policy Violations

Medium
Confidence
98% confidence
Finding
The command-line interface sets `--language` to `zh` by default, meaning the skill will operate in a specific language unless the user overrides it. This is a natural-language locale policy issue because the user is not first offered a neutral default or explicit opt-in.

Tainted flow: 'path' from os.environ.get (line 294, credential/environment) → open (file write)

Medium
Category
Data Flow
Content
def _write_srt(segments, path):
    """Write SRT subtitle file."""
    with open(path, 'w', encoding='utf-8') as f:
        for i, seg in enumerate(segments, 1):
            start = _fmt_timestamp(seg['start'])
            end = _fmt_timestamp(seg['end'])
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Tainted flow: 'path' from os.environ.get (line 294, credential/environment) → open (file write)

Medium
Category
Data Flow
Content
def _write_srt(segments, path):
    """Write SRT subtitle file."""
    with open(path, 'w', encoding='utf-8') as f:
        for i, seg in enumerate(segments, 1):
            start = _fmt_timestamp(seg['start'])
            end = _fmt_timestamp(seg['end'])
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The command-line interface sets `--language` to `zh` by default, which imposes a specific language/locale choice on users unless they explicitly override it. This matches the policy category for language or locale constraints without opt-in, especially since the tool also advertises multi-language support elsewhere in the file.

Scope Creep

Low
Category
Excessive Agency
Content
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Static analysis

No suspicious patterns detected.