Back to skill

Security audit

video-merger

Security checks for vulnerabilities and agentic risk

Overview

This video-merging skill is mostly purpose-aligned, but it has a real unsafe filename-handling flaw and runs system and FFmpeg commands that users should review before use.

Review before installing. Use this only on video directories and filenames you trust, avoid attacker-supplied clip names, choose output paths carefully, and inspect the install script before allowing it to install FFmpeg with sudo or a system package manager.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
src/video_merger.py:97
Finding
FFmpeg Concat Manifest Injection Through Unescaped Filenames<![CDATA[ ## Vulnerability Details **File Location**: `src/video_merger.py:97-115` and `src/video_merger.py:239-257` **Vulnerability Type**: Injection into an FFmpeg concat-demuxer manifest **Risk Level**: Medium ### Vulnerable Code The full-video merge path constructs a concat manifest directly from filenames and then processes it with unsafe path checks disabled: ```python # 生成concat列表 with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f: for v in video_list: f.write(f"file '{os.path.abspath(v)}'\n") concat_file = f.name try: # 先无损拼接所有片段 with tempfile.NamedTemporaryFile(suffix='.mp4', delete=False) as f: temp_raw = f.name cmd_concat = [ self.ffmpeg_path, "-y", "-f", "concat", "-safe", "0", "-i", concat_file, "-c", "copy", temp_raw ] print("正在拼接视频片段...") subprocess.run(cmd_concat, capture_output=True, check=True) ``` The chunked merge path repeats the same vulnerable pattern: ```python # 生成concat列表 with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f: for v in video_list: f.write(f"file '{os.path.abspath(v)}'\n") concat_file = f.name try: # 先无损拼接所有片段 with tempfile.NamedTemporaryFile(suffix='.mp4', delete=False) as f: temp_raw = f.name cmd_concat = [ self.ffmpeg_path, "-y", "-f", "concat", "-safe", "0", "-i", concat_file, "-c", "copy", temp_raw ] print(f"正在拼接分块 {os.path.basename(output_path)},包含 {len(video_list)} 个片段...") subprocess.run(cmd_concat, capture_output=True, check=True) ``` ### Technical Analysis `get_sorted_videos()` only requires a filename to begin with a numeric prefix followed by an underscore and end in `.mp4`. It does not reject apostrophes, carriage returns, newline characters, or other concat-manifest syntax. The selected filename is embedded between single quotes without FFmpeg concat-demuxer escaping: ```python f.write(f" ...[truncated 3044 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Reject manifest control characters** - Reject filenames containing `\r`, `\n`, NUL, or other control characters. - Reject or correctly encode apostrophes according to FFmpeg concat-demuxer quoting rules. - Perform validation before creating the manifest. 2. **Use a dedicated FFmpeg concat-path encoder** - Do not rely on generic shell escaping because concat-manifest syntax is not shell syntax. - Generate each `file` directive using escaping explicitly documented for the FFmpeg concat demuxer. - Prefer a tested library routine rather than manually combining quotes and paths. 3. **Restore safe-path enforcement** - Remove `-safe 0` unless absolute paths are strictly necessary. - If absolute paths are required, independently enforce path containment before disabling FFmpeg's safety check. 4. **Enforce input-directory containment** - Resolve the input directory with `Path.resolve()`. - Resolve every candidate path and verify it remains beneath the resolved input directory. - Define an explicit policy for symbolic links; reject them if following links outside the input directory is not required. 5. **Restrict FFmpeg protocols** - Supply a minimal `-protocol_whitelist` appropriate for local file processing. - Do not enable HTTP, pipe, concat, or other unnecessary protocols for manifest inputs. 6. **Add security regression tests** Test filenames containing: ```text ' \r \n file ' http: pipe: # ``` Tests should confirm that malicious names are rejected before FFmpeg is invoked and that generated manifests cannot contain attacker-created directives. 7. **Apply the fix to both code paths** - Update the manifest generation in `merge()`. - Update the duplicate manifest generation in `_merge_single_chunk()`. - Prefer a single hardened helper function so the two implementations cannot diverge. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • 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
Findings (23)

Chaining Abuse

High
Category
Tool Misuse
Content
if command -v brew &> /dev/null; then
        brew install ffmpeg
    elif command -v apt &> /dev/null; then
        sudo apt update && sudo apt install -y ffmpeg
    else
        echo "请手动安装ffmpeg:https://ffmpeg.org/download.html"
        exit 1
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The natural-language content and usage guidance are presented only in Chinese, which can amount to forcing a specific language without user opt-in. The policy for this category calls out language or locale constraints unless the skill offers a language choice or clearly justifies a region-specific limitation.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
brew install ffmpeg

# Ubuntu/Debian
sudo apt install ffmpeg
```

### 2. 安装video-merger
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill advertises executable installation and script usage, which implies shell and file access, but it does not declare any explicit tool scope or permissions boundaries. This can lead to overbroad execution in agent environments, making it harder to enforce least privilege and increasing the chance of unintended file access or command execution.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The manifest description and main documentation are written entirely in Chinese, which creates an implicit language constraint for users. Under the language/locale policy rule, this is a natural-language policy concern when no opt-in, alternative language, or justification for the locale restriction is provided.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The trigger list is broader than the skill’s actual scope: terms like "video", "merge", and "concat" are generic and can cause the skill to activate for many ordinary video-editing requests beyond segmented short-video merging. Over-broad activation increases the chance of inappropriate routing or unintended execution of file-processing behavior on user media, which is a real security/reliability issue even though the metadata does not show obviously malicious content.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This shell script runs `sudo apt update && sudo apt install -y ffmpeg`, which changes the system by installing packages and may prompt for elevated privileges. Although the script prints progress messages, it does not clearly warn the user that it will modify the system package state or request confirmation before doing so.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# No external Python dependencies required!
# Only needs ffmpeg installed on system:
# macOS: brew install ffmpeg
# Ubuntu/Debian: sudo apt install ffmpeg
# Windows: Download from https://ffmpeg.org/download.html
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# No external Python dependencies required!
# Only needs ffmpeg installed on system:
# macOS: brew install ffmpeg
# Ubuntu/Debian: sudo apt install ffmpeg
# Windows: Download from https://ffmpeg.org/download.html
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This code file contains natural-language descriptions and user-facing status/error text in Chinese, beginning with the module docstring and constructor docstring, with no indication that language is selectable or that the skill is intended only for a Chinese-speaking context. The policy scope for SQP-3 applies to all file types, including comments, docstrings, and string literals, so this constitutes a locale/language policy issue.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"""检查依赖是否安装"""
        for tool in [self.ffmpeg_path, self.ffprobe_path]:
            try:
                subprocess.run([tool, "-version"], capture_output=True, check=True)
            except Exception as e:
                raise RuntimeError(f"未找到{tool},请先安装ffmpeg:https://ffmpeg.org/download.html") from e
Confidence
93% confidence
Finding
The constructor accepts ffmpeg_path and ffprobe_path and executes them directly. If an untrusted caller can supply these paths, they can cause execution of an arbitrary local binary or script under the privileges of the running process, which is a genuine command-execution risk even without shell=True.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"-of", "default=noprint_wrappers=1:nokey=1",
            video_path
        ]
        result = subprocess.run(cmd, capture_output=True, text=True, check=True)
        width, height, duration = result.stdout.strip().split("\n")[:3]
        return int(width), int(height), float(duration)
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
temp_raw
            ]
            print("正在拼接视频片段...")
            subprocess.run(cmd_concat, capture_output=True, check=True)

            # 获取总时长
            _, _, total_duration = self.get_video_info(temp_raw)
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
temp_raw
            ]
            print("正在拼接视频片段...")
            subprocess.run(cmd_concat, capture_output=True, check=True)

            # 获取总时长
            _, _, total_duration = self.get_video_info(temp_raw)
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
"-c:a", "aac", "-ar", "44100", "-ac", "2",
                output_path
            ]
            subprocess.run(cmd_final, capture_output=True, check=True)

            # 验证输出文件
            if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
Confidence
89% confidence
Finding
The code passes user-influenced values such as resolution, fps, transition_duration, crf, preset, and especially output_path directly into an ffmpeg invocation without validation. While shell injection is avoided, untrusted parameters can still trigger dangerous ffmpeg behaviors such as writing to arbitrary filesystem locations, selecting unintended protocols/devices depending on ffmpeg build/configuration, or causing resource exhaustion through extreme encoding settings.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"-c:a", "aac", "-ar", "44100", "-ac", "2",
                output_path
            ]
            subprocess.run(cmd_final, capture_output=True, check=True)

            return True
Confidence
88% confidence
Finding
This final ffmpeg encoding step accepts unvalidated parameters and an output path that may be attacker-controlled through the library API. In the context of a video-merging skill, arbitrary output destinations and unconstrained encoding values increase risk of file overwrite, misuse of ffmpeg-supported sinks/protocols, and denial-of-service via expensive transcoding workloads.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
This markdown file presents its changelog and linked standards entirely in Chinese, which constitutes a natural-language locale choice. The file does not indicate that the Chinese locale is optional or justified as region-specific, so it may violate a language/locale policy requiring user opt-in or explicit documentation.

Natural-Language Policy Violations

Low
Confidence
92% confidence
Finding
This markdown file contains policy text only in Chinese and does not offer an alternative language or note that the locale is intentionally region-specific. Under the natural-language policy rule, forcing a specific language without user opt-in can be a policy concern.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
This markdown file contains user-facing instructions exclusively in Chinese, including headings and all contribution steps. Under the language/locale policy, forcing a specific language without user opt-in can be a natural-language policy violation unless the locale constraint is explicitly documented and justified.

Missing User Warnings

Low
Confidence
77% confidence
Finding
This markdown file documents a command that creates an output file path but does not mention whether existing files may be overwritten or that running the command will write a new media file to disk. For markdown files, the guidance asks for warnings when behaviour could affect user data or system integrity, and file-writing behavior is described here without any cautionary note.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The manifest description and tags are entirely in Chinese, which suggests the skill is presented in a single language without any stated user opt-in or justification for a locale-specific scope. Under the policy, language constraints should either offer choice or be clearly documented as region-specific.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
All user-facing messages in the script are in Chinese, with no opt-in, fallback, or indication that the skill is intended only for Chinese-speaking users. This can violate language/locale policy when a skill imposes a language choice without user selection or documented justification.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
This code includes user-facing Chinese-language text in the module docstring and prints errors in Chinese, but does not provide any language or locale selection. That can violate a language/locale policy when users are not explicitly opted into Chinese output.

Static analysis

No suspicious patterns detected.