Back to skill

Security audit

Ai Video Gen

Security checks for vulnerabilities and agentic risk

Overview

The skill is generally an AI video generator, but it overstates supported features and has under-scoped cloud/API and local file handling risks users should review before installing.

Install only if you are comfortable sending prompts and narration to cloud AI providers and using paid API keys. Use a virtual environment, keep .env out of version control, avoid sensitive prompts/media, run scripts in a private working directory, and verify provider support before relying on Runway, ElevenLabs, or the missing helper scripts.

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)

T09 · Insecure Skill Coding Practices

Warning
Location
images_to_video.py:25
Finding

Predictable Temporary Manifest Allows Local File Clobbering

Content
View full analysis

Vulnerability Details

File Location: images_to_video.py, lines 25-30 and 53-56
Vulnerability Type: Predictable temporary file, symlink following, and unsafe FFmpeg manifest construction
Risk Level: Medium

Vulnerable Code

python
# Create temporary file list
file_list_path = Path('filelist.txt')
with open(file_list_path, 'w') as f:
    for img in image_files:
        duration = 1.0 / fps
        f.write(f"file '{Path(img).absolute()}'\n")
        f.write(f"duration {duration}\n")

# FFmpeg command
cmd = [
    'ffmpeg', '-y',
    '-f', 'concat',
    '-safe', '0',
    '-i', str(file_list_path),
    '-vsync', 'vfr',
    '-pix_fmt', 'yuv420p',
    '-crf', str(crf),
    output_path
]

try:
    result = subprocess.run(cmd, capture_output=True, text=True, check=True)
    print(f"✅ Video created: {output_path}")
    return output_path
except subprocess.CalledProcessError as e:
    print(f"❌ FFmpeg error: {e.stderr}")
    sys.exit(1)
finally:
    # Clean up temp file
    if file_list_path.exists():
        file_list_path.unlink()

Technical Analysis

The script uses the fixed filename filelist.txt in the process's current working directory. It opens that path in write mode without exclusive creation and without checking whether it is a symbolic link. On platforms that follow symbolic links during file opening, an attacker with write access to the working directory can pre-create filelist.txt as a symlink to another file writable by the victim. The subsequent open(..., 'w') operation follows the link and truncates the target file.

The finally block then deletes the predictable path. In the symlink scenario, this normally deletes the symlink rather than the linked target, making the attack artifact less persistent while leaving the target corrupted.

Image paths are also interpolated directly into FFmpeg concat-demuxer syntax. Filenames containing single quotes, carriage returns, or newline characters can alter the generated manife ...[truncated 1765 chars]

Remediation
View remediation

Remediation Suggestions

  1. Create the manifest through Python's tempfile module using exclusive, unpredictable file creation:
python
import os
import tempfile

manifest_path = None

try:
    with tempfile.NamedTemporaryFile(
        mode="w",
        encoding="utf-8",
        prefix="ai-video-",
        suffix=".ffconcat",
        delete=False
    ) as manifest:
        manifest_path = manifest.name

        for image in image_files:
            resolved = Path(image).resolve(strict=True)
            escaped = str(resolved).replace("'", "'\\''")
            manifest.write(f"file '{escaped}'\n")
            manifest.write(f"duration {1.0 / fps}\n")

    cmd = [
        "ffmpeg", "-y",
        "-f", "concat",
        "-safe", "0",
        "-i", manifest_path,
        "-vsync", "vfr",
        "-pix_fmt", "yuv420p",
        "-crf", str(crf),
        output_path,
    ]
    subprocess.run(cmd, capture_output=True, text=True, check=True)
finally:
    if manifest_path:
        Path(manifest_path).unlink(missing_ok=True)
  1. Apply FFmpeg concat-demuxer escaping rules to every filename. Reject filenames containing carriage returns or newline characters if robust escaping cannot be guaranteed.

  2. Resolve and validate all input paths before writing the manifest. Require regular files where appropriate.

  3. Avoid creating temporary state in the caller's working directory.

  4. Preserve list-based subprocess.run invocation and do not introduce shell=True.

  5. Add tests covering symbolic links, concurrent executions, single quotes, newlines, and unusual Unicode filenames.

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Unpinned Dependencies Permit Installation of Unreviewed Future Releases

Content
View full analysis

Vulnerability Details

File Location: requirements.txt, lines 1-5
Related Installation Instructions: README.md, line 18; SKILL.md, line 56
Vulnerability Type: Non-reproducible dependency resolution without integrity hashes
Risk Level: Low

Vulnerable Code

text
openai>=1.0.0
replicate>=0.20.0
requests>=2.31.0
pillow>=10.0.0
python-dotenv>=1.0.0

The documented installation commands resolve these unconstrained versions:

bash
pip install -r requirements.txt
bash
pip install openai requests pillow replicate python-dotenv

Technical Analysis

Every dependency specifies only a minimum version. There is no upper bound, exact version, lock file, or package hash. Consequently, two installations performed at different times can retrieve materially different dependency trees.

This is not evidence that any currently named package is malicious. The package names are consistent with the declared functionality, and the audit found no suspicious custom package index or obvious typosquatting. The risk arises because future, unreviewed releases automatically satisfy the constraints.

Python packages can execute code during installation and subsequently execute code when imported. A compromised upstream account, malicious release, dependency compromise, or unexpected breaking change could therefore affect users without any modification to this project.

Attack Path

  1. A user follows the documented pip install command.
  2. pip queries its configured package index and resolves the newest releases satisfying the lower-bound constraints.
  3. A future compromised, malicious, or otherwise unreviewed release satisfies those constraints.
  4. The package and its transitive dependencies are downloaded without verification against project-maintained hashes.
  5. Package installation or later import executes the affected code with the privileges of the installing or running user.

This path depends on an upstream or ...[truncated 848 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin direct dependencies to exact versions that have been tested and reviewed:
text
openai==<reviewed-version>
replicate==<reviewed-version>
requests==<reviewed-version>
pillow==<reviewed-version>
python-dotenv==<reviewed-version>
  1. Generate a lock file that also fixes transitive dependency versions.

  2. Use hash verification, such as a requirements file generated with pip-compile --generate-hashes, and install with:

bash
pip install --require-hashes -r requirements.txt
  1. Build and install dependencies in an isolated virtual environment rather than into a privileged or system-wide Python installation.

  2. Review dependency release notes and security advisories before updating pinned versions.

  3. Use automated dependency scanning while requiring human review and tests before accepting upgrades.

  4. Document the expected Python and FFmpeg versions so the complete runtime environment is reproducible.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (33)

Tainted flow: 'image_url' from os.getenv (line 49, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The code downloads a URL returned by an external API without validating the scheme, host, size, or content type. If that upstream response is compromised or malformed, the program can be induced to fetch unexpected resources, creating SSRF-like behavior or downloading malicious/unbounded content into local storage.

Content

Scanner excerpt · generate_video.py (reported line 53)May include surrounding context.

python
# Download image
        img_path = self.output_dir / f"image_{int(time.time())}.png"
        img_data = requests.get(image_url).content
        with open(img_path, 'wb') as f:
            f.write(img_data)

Tainted flow: 'headers' from os.getenv (line 94, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · generate_video.py (reported line 106)May include surrounding context.

python
"prompt": prompt or "animate this image"
        }
        
        response = requests.post(
            "https://api.lumalabs.ai/dream-machine/v1/generations",
            headers=headers,
            json=data

Tainted flow: 'headers' from os.getenv (line 94, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · generate_video.py (reported line 119)May include surrounding context.

python
# Poll for completion
        while True:
            status = requests.get(
                f"https://api.lumalabs.ai/dream-machine/v1/generations/{generation_id}",
                headers=headers
            ).json()

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · QUICK_START.md (reported line 16)May include surrounding context.

md
1. Go to https://lumalabs.ai
2. Sign up (has free tier!)
3. Get API key from dashboard

**Cost:** FREE for first 30 videos/month

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · QUICK_START.md (reported line 26)May include surrounding context.

bash
cd skills/ai-video-gen
copy .env.example .env

Edit .env and add:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

bash
cd skills/ai-video-gen
copy .env.example .env

Edit .env and add:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

bash
copy .env.example .env
notepad .env

Minimum required:

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

If the skill is presented as a full AI video generation pipeline but does not actually implement the advertised integrations or workflow, users may make security and privacy assumptions that are false. Misrepresentation of capabilities undermines reviewability and can hide what the tool really does, which is risky in a skill that is expected to handle prompts, media files, APIs, and shell-based editing.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

If the skill is presented as a full AI video generation pipeline but does not actually implement the advertised integrations or workflow, users may make security and privacy assumptions that are false. Misrepresentation of capabilities undermines reviewability and can hide what the tool really does, which is risky in a skill that is expected to handle prompts, media files, APIs, and shell-based editing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README tells users to place live API keys into a local .env file but does not warn that these secrets must be kept private, excluded from version control, and never shared in screenshots, logs, or support requests. In a skill centered on multiple paid external AI services, this omission increases the chance of accidental credential disclosure and subsequent unauthorized API use or billing abuse.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill advertises and documents capabilities that require environment access, network calls, shell execution, and file writes, but the manifest does not declare any explicit tool scope or permissions. This increases the risk of over-privileged execution because reviewers and users cannot easily determine what the skill is expected to access, making misuse or accidental dangerous behavior harder to constrain.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill encourages use of third-party AI APIs for image generation, video synthesis, and voice-over but does not warn that prompts, images, audio, or video may be transmitted to external providers. This creates a meaningful privacy and compliance risk because users may inadvertently send sensitive or proprietary media to cloud services without informed consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

User-supplied text passed via --text is transmitted to OpenAI's TTS service without an explicit warning, consent prompt, or clear documentation at the point of use. In a video-generation skill, prompts may contain sensitive business, personal, or confidential content, so silent third-party transmission creates a real privacy and data-handling risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The tool transmits user-generated content to a third-party video service without any explicit warning or consent flow, and the implementation appears to send a local file path string rather than a proper upload token/object. In a skill that may process sensitive prompts or locally generated media, undisclosed third-party transmission raises privacy and data-handling risk.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · generate_video.py (reported line 106)May include surrounding context.

python
"prompt": prompt or "animate this image"
        }
        
        response = requests.post(
            "https://api.lumalabs.ai/dream-machine/v1/generations",
            headers=headers,
            json=data

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · generate_video.py (reported line 106)May include surrounding context.

python
"prompt": prompt or "animate this image"
        }
        
        response = requests.post(
            "https://api.lumalabs.ai/dream-machine/v1/generations",
            headers=headers,
            json=data

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · generate_video.py (reported line 107)May include surrounding context.

python
}
        
        response = requests.post(
            "https://api.lumalabs.ai/dream-machine/v1/generations",
            headers=headers,
            json=data
        )

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · generate_video.py (reported line 120)May include surrounding context.

python
}
        
        response = requests.post(
            "https://api.lumalabs.ai/dream-machine/v1/generations",
            headers=headers,
            json=data
        )

Tainted flow: 'generation_id' from requests.post (line 115, network input) → requests.get (network output)

Medium
Category
Data Flow
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.

Content

Scanner excerpt · generate_video.py (reported line 119)May include surrounding context.

python
# Poll for completion
        while True:
            status = requests.get(
                f"https://api.lumalabs.ai/dream-machine/v1/generations/{generation_id}",
                headers=headers
            ).json()

Tainted flow: 'video_url' from requests.get (line 125, network input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
90% confidence
Finding

The code follows a video URL supplied by prior network data and downloads it without validating the destination or limiting the response. That allows an untrusted API response to redirect the tool to arbitrary remote content, potentially causing SSRF-style requests, oversized downloads, or ingestion of malicious files.

Content

Scanner excerpt · generate_video.py (reported line 135)May include surrounding context.

python
# Download video
        video_path = self.output_dir / f"video_{int(time.time())}.mp4"
        video_data = requests.get(video_url).content
        with open(video_path, 'wb') as f:
            f.write(video_data)

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 · generate_video.py (reported line 180)May include surrounding context.

python
output_path
        ]
        
        result = subprocess.run(cmd, capture_output=True, text=True)
        
        if result.returncode != 0:
            raise Exception(f"FFmpeg error: {result.stderr}")

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The command-line interface presents 'runway' as a supported --video-model choice, which implies the selected provider will actually be used. However, when 'runway' is chosen, the code prints that Runway support is 'coming soon' and still calls the Luma generation path, so the documented behavior contradicts the implementation.

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 · add_voiceover.py (reported line 70)May include surrounding context.

python
]
    
    try:
        result = subprocess.run(cmd, capture_output=True, text=True, check=True)
        print(f"✅ Video created: {output_path}")
        return output_path
    except subprocess.CalledProcessError as e:

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 · images_to_video.py (reported line 47)May include surrounding context.

python
]
    
    try:
        result = subprocess.run(cmd, capture_output=True, text=True, check=True)
        print(f"✅ Video created: {output_path}")
        return output_path
    except subprocess.CalledProcessError as e:

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The example commands write output media files but do not warn that existing files may be overwritten or that substantial disk space may be used. In a media-generation skill, this can lead to accidental data loss or unexpected local resource consumption, especially when users copy-paste commands directly.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.