Back to skill

Security audit

Video A'Roll Auto Editor v4.7

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent video-editing skill, but its batch cleanup can recursively delete a user-supplied work directory without sufficient guardrails.

Review before installing or running batch mode. Use only a fresh, dedicated temporary work directory that contains nothing you need, avoid running as root, and be careful with video filenames from untrusted sources. The skill appears purpose-built for Chinese talking-head video rough cuts, but the cleanup behavior should be fixed or tightly controlled before routine use.

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
video_editor_auto_v4.6.py:569
Finding

User-Controlled Recursive Directory Deletion During Batch Cleanup

Content
View full analysis

Vulnerability Details

File Location: video_editor_auto_v4.6.py:569 and video_editor_auto_v4.6.py:606-611
Vulnerability Type: Unrestricted recursive deletion of a user-controlled path
Risk Level: High

Vulnerable Code

python
# Phase 4: Clean intermediate files (individual clips + temp audio)
for c in clips:
    if os.path.exists(c.clip_path):
        os.remove(c.clip_path)
if os.path.exists(work_dir):
    shutil.rmtree(work_dir, ignore_errors=True)

The directory is obtained directly from a command-line argument:

python
if len(sys.argv) >= 2 and os.path.isdir(sys.argv[1]):
    input_dir = sys.argv[1]
    output_dir = sys.argv[2] if len(sys.argv) > 2 else "./output"
    work_dir = sys.argv[3] if len(sys.argv) > 3 else "./video_work"
    os.makedirs(output_dir, exist_ok=True)
    os.makedirs(work_dir, exist_ok=True)
    process_batch(input_dir, output_dir, work_dir)

Technical Analysis

In batch mode, the third command-line argument directly determines work_dir. After successful processing and concatenation, the application passes this path to shutil.rmtree() without verifying that it is a temporary directory created by the application.

The code does not canonicalize the path, check whether it is the input or output directory, reject sensitive locations, verify directory ownership, detect symlink-based redirection, or require an application-specific marker. The initial os.makedirs(work_dir, exist_ok=True) does not establish that the directory is safe to delete because an existing arbitrary directory is accepted.

This is particularly dangerous because shutil.rmtree() recursively removes the directory and its contents. The use of ignore_errors=True also suppresses cleanup errors, reducing visibility into partial destructive operations.

Attack Path

  1. An attacker provides or recommends a batch-processing command with a sensitive writable directory as t ...[truncated 1093 chars]
Remediation
View remediation

Remediation Suggestions

  • Create the working directory internally with tempfile.mkdtemp() or tempfile.TemporaryDirectory() rather than accepting an arbitrary cleanup target.
  • Retain the canonical path returned by the temporary-directory API and delete only that exact generated directory.
  • Resolve paths with os.path.realpath() or pathlib.Path.resolve() before validation and deletion.
  • Explicitly reject the filesystem root, user home directory, current working directory, input directory, output directory, and their parent directories.
  • Ensure the cleanup target is located beneath a dedicated application-controlled temporary root.
  • Refuse symlink cleanup targets and check that no path component redirects outside the expected temporary root.
  • Consider deleting only the known files generated during the current run instead of recursively deleting an entire caller-selected directory.
  • Remove ignore_errors=True, handle expected errors explicitly, and report cleanup failures to the user.
  • If a custom work directory remains supported, create a unique child directory inside it and delete only that child directory.

T09 · Insecure Skill Coding Practices

Warning
Location
video_editor_auto_v4.6.py:357
Finding

FFmpeg Concat Manifest Injection Through Unescaped Filenames

Content
View full analysis

Vulnerability Details

File Location: video_editor_auto_v4.6.py:357-369
Vulnerability Type: Unsafe construction of an FFmpeg concat manifest
Risk Level: Medium

Vulnerable Code

python
def concat_videos(clip_paths, output_path):
    """Concatenate video list using FFmpeg concat protocol"""
    list_file = output_path + ".list.txt"
    with open(list_file, 'w') as f:
        for p in clip_paths:
            f.write(f"file '{os.path.abspath(p)}'\n")
    cmd = [
        "ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", list_file,
        "-c:v", "libx264", "-crf", str(CONFIG['crf']), "-preset", CONFIG['preset'],
        "-c:a", "aac", "-b:a", CONFIG['audio_bitrate'],
        output_path
    ]
    ok = subprocess.run(cmd, capture_output=True, text=True).returncode == 0

Technical Analysis

Each clip path is inserted into an FFmpeg concat-demuxer manifest without escaping characters that have syntactic significance, including single quotes, backslashes, carriage returns, and newlines. Clip filenames are derived from input video basenames, so an attacker who can place files in the processed batch directory can influence the generated manifest.

A crafted filename containing a quote or newline can terminate the intended file entry and introduce additional manifest content. The use of -safe 0 disables FFmpeg's normal safe-path restrictions, increasing the range of paths the manifest is allowed to reference.

This is not shell command injection: subprocess.run() receives an argument list and does not invoke a shell. The vulnerability occurs in the separately parsed FFmpeg concat manifest.

Attack Path

  1. An attacker creates a supported video file in the batch input directory with a filename containing concat-manifest control characters, such as a quote or newline.
  2. Batch processing derives video_name from that filename and creates a clip whose path includes the attacker-c ...[truncated 1164 chars]
Remediation
View remediation

Remediation Suggestions

  • Reject input basenames containing control characters, carriage returns, newlines, null bytes, quotes, or other characters unsafe for concat manifests.
  • Escape paths according to the FFmpeg concat-demuxer syntax rather than relying only on surrounding single quotes.
  • Generate intermediate clip names internally using safe identifiers instead of preserving untrusted input basenames.
  • Keep all intermediate clips under a canonical application-controlled directory and verify every resolved path is beneath it.
  • Avoid -safe 0 where possible. Retain FFmpeg's safe-path validation and use relative paths beneath the manifest directory.
  • Create the manifest with restrictive permissions and a unique temporary filename.
  • Add tests covering filenames containing quotes, backslashes, Unicode characters, carriage returns, and newlines.

T08 · Insecure Dependencies

Note
Location
SKILL.md:38
Finding

Unpinned Third-Party Dependency Installation

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:38-46 and README.md:26-34
Vulnerability Type: Unpinned and unhashed dependency installation
Risk Level: Low

Vulnerable Documentation

bash
# macOS
brew install ffmpeg
pip install openai-whisper

# Ubuntu / Debian
sudo apt install ffmpeg
pip install openai-whisper

The same installation pattern appears in both SKILL.md and README.md.

Technical Analysis

The installation instructions request the latest package version available from the user's configured Python package index. No exact version, dependency lock file, package hash, or trusted-index requirement is supplied.

Consequently, installation results can change over time and across environments. The effective dependency set includes mutable transitive dependencies selected by pip at installation time. The documentation also describes a requirements.txt file in the expected project structure, but no such file is present in the supplied project.

This does not prove that openai-whisper is malicious. The risk arises from mutable, unverified dependency resolution and the execution of package installation or runtime code that was not fixed at audit time.

Attack Path

  1. A user follows the documented pip install openai-whisper command.
  2. Pip consults the user's configured package index and resolves the latest permitted release and transitive dependencies.
  3. A future compromised release, compromised transitive dependency, unsafe index configuration, or incompatible update is selected.
  4. Package build or installation hooks may execute during installation, and installed package code executes when the application invokes Whisper.
  5. That code runs with the privileges of the user performing installation or running the application.

Impact Assessment

A compromised dependency could execute arbitrary code with the installing or invoking user's privileges, access that us ...[truncated 421 chars]

Remediation
View remediation

Remediation Suggestions

  • Add a reviewed dependency file containing exact package and transitive dependency versions.
  • Generate and verify cryptographic hashes for all downloaded artifacts.
  • Install with a command such as pip install --require-hashes -r requirements.txt.
  • Use a controlled virtual environment and document a trusted package index explicitly.
  • Review and update locked dependencies through a controlled process with vulnerability scanning and regression testing.
  • Pin the FFmpeg package or document tested minimum and maximum versions where the operating-system package manager permits it.
  • Ensure the documented project structure matches the distributed package and includes the referenced dependency file.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (16)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This markdown file states that transcription uses "Whisper CLI (Chinese)" and later defines fluency logic around Chinese filler words and Chinese connective endings. That forces a specific language/locale behavior in the skill description without user opt-in, which matches the policy-violation category for language or locale constraints.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · README.md (reported line 33)May include surrounding context.

pip install openai-whisper

Ubuntu / Debian

sudo apt install ffmpeg pip install openai-whisper

text

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

pip install openai-whisper

Ubuntu / Debian

sudo apt install ffmpeg pip install openai-whisper

text

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The documentation states the skill is tuned for Chinese speech and marks non-Chinese content as not adapted, which creates a language-specific constraint in natural language. There is no user choice, opt-in flow, or explicit region-specific justification accompanying this limitation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation states elsewhere that batch mode cleans intermediate files, but the user-facing quick-start for batch processing does not prominently warn that only the final output and batch report remain. This can cause unexpected deletion of intermediate artifacts a user may rely on for review, auditing, or recovery, creating a real safety/usability risk even if not a code-execution flaw.

Content

No source excerpt is available for this finding.

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 · video_editor_auto_v4.6.py (reported line 88)May include surrounding context.

python
"-af", f"silencedetect=noise={CONFIG['silence_noise']}dB:d={CONFIG['silence_duration']}",
        "-f", "null", "-"
    ]
    result = subprocess.run(cmd, capture_output=True, text=True)
    starts = re.findall(r'silence_start: ([\d.]+)', result.stderr)
    ends = re.findall(r'silence_end: ([\d.]+)', result.stderr)
    return [(float(starts[i]), float(ends[i])) for i in range(min(len(starts), len(ends)))]

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 · video_editor_auto_v4.6.py (reported line 391)May include surrounding context.

python
"-af", f"silencedetect=noise={CONFIG['silence_noise']}dB:d={CONFIG['silence_duration']}",
        "-f", "null", "-"
    ]
    result = subprocess.run(cmd, capture_output=True, text=True)
    starts = re.findall(r'silence_start: ([\d.]+)', result.stderr)
    ends = re.findall(r'silence_end: ([\d.]+)', result.stderr)
    return [(float(starts[i]), float(ends[i])) for i in range(min(len(starts), len(ends)))]

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 · video_editor_auto_v4.6.py (reported line 178)May include surrounding context.

python
def transcribe_segment(video_path, seg, work_dir):
    """Extract segment audio and transcribe via Whisper"""
    audio_path = os.path.join(work_dir, f"segment_{seg.index}.wav")
    subprocess.run([
        "ffmpeg", "-y", "-i", video_path,
        "-ss", str(seg.start_time), "-to", str(seg.end_time),
        "-vn", "-ar", "16000", "-ac", "1", audio_path

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 · video_editor_auto_v4.6.py (reported line 188)May include surrounding context.

python
print(f"    ⚠️  Audio extraction failed: segment_{seg.index}")
        return ""
    try:
        subprocess.run([
            "python3", "-m", "whisper", audio_path,
            "--model", "small", "--language", "zh",
            "--output_format", "txt", "--output_dir", work_dir

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The Whisper invocation hard-codes --language zh, which enforces a specific language/locale policy for all transcription runs. This removes user choice and may violate organizational requirements against forcing a language without opt-in.

Content

No source excerpt is available for this finding.

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 · video_editor_auto_v4.6.py (reported line 355)May include surrounding context.

python
"-c:a", "aac", "-b:a", CONFIG['audio_bitrate'],
        output_path
    ]
    return subprocess.run(cmd, capture_output=True, text=True).returncode == 0

def concat_videos(clip_paths, output_path):
    """Concatenate video list using FFmpeg concat protocol"""

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
77% confidence
Finding

The concat step writes attacker-influenced file paths into an ffmpeg concat list without escaping embedded quotes or special characters. A crafted filename containing a single quote or concat-directive-like content can corrupt the list format and potentially cause ffmpeg to read unintended files, which is more dangerous here because batch mode ingests arbitrary filenames from a directory.

Content

Scanner excerpt · video_editor_auto_v4.6.py (reported line 369)May include surrounding context.

python
"-c:a", "aac", "-b:a", CONFIG['audio_bitrate'],
        output_path
    ]
    ok = subprocess.run(cmd, capture_output=True, text=True).returncode == 0
    if os.path.exists(list_file):
        os.remove(list_file)
    return ok

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 · video_editor_auto_v4.6.py (reported line 430)May include surrounding context.

python
print("\n🎤 Step 6: Transcribing candidates...")
    whisper_available = True
    try:
        if subprocess.run(["python3", "-m", "whisper", "--help"], capture_output=True, text=True, timeout=10).returncode != 0:
            whisper_available = False
    except Exception:
        whisper_available = False

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Batch mode unconditionally deletes generated clips and recursively removes the work directory after concatenation, without explicit user confirmation or guardrails. In a skill context that may be run on user-specified paths, this can cause unexpected data loss, and the risk increases because work_dir is taken from command-line input and then passed to shutil.rmtree.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The markdown states that intermediate artifacts are 'automatically cleaned' after batch processing, which implies file deletion. Because this behavior can affect user data in the working directory, the documentation should explicitly warn users that temporary files will be removed and clarify which paths are affected.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The top-level documentation for Scenario B says 'Batch processing -> cross-video dedup -> concatenation', which describes selection and output assembly but omits the destructive cleanup behavior implemented later. In code, Scenario B also removes all intermediate clip files and recursively deletes the work directory, which is a meaningful side effect not reflected by that scenario description.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.