Back to skill

Security audit

HeyVideoGen

Security checks for vulnerabilities and agentic risk

Overview

This video-generation skill appears purpose-aligned, but it needs review because ordinary video inputs can reach unsafe local command execution paths.

Install only if you are comfortable reviewing and constraining the runner first. Prefer replacing shell=True with argument-list subprocess calls, validating project names and paths, pinning HyperFrames dependencies, and running media generation in a sandbox with only the intended workspace and API credentials exposed.

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
scripts/run_heyvideogen.py:25
Finding

Shell Command Injection Through User-Controlled Project Names and Paths

Content
View full analysis

Vulnerability Details

File Location: scripts/run_heyvideogen.py, lines 25-38 and 131-138
Vulnerability Type: OS command injection and unrestricted project-path handling
Risk Level: High

python
def cmd(cmd: str, cwd=None, shell=True):
    print(f"\n>>> {cmd}")
    result = subprocess.run(cmd, cwd=cwd, shell=shell, capture_output=False)
    return result.returncode == 0


def run_init(project_name: str):
    """初始化 HyperFrames 项目"""
    target = PROJECT_ROOT / project_name
    if target.exists():
        print(f"⚠️  项目 {project_name} 已存在")
        return

    rc = cmd(f"npx hyperframes init {project_name} --non-interactive", cwd=PROJECT_ROOT)

The render path contains a second instance of the same unsafe pattern:

python
def run_render(project: str):
    """渲染 HyperFrames 项目"""
    project_path = PROJECT_ROOT / project
    output = project_path / "heyvideogen-output" / "final.mp4"
    print(f"\n🎬 开始渲染:{project_path}")
    ok = cmd(f"npx hyperframes lint", cwd=project_path)
    if not ok:
        print("⚠️  Lint 有警告,继续渲染...")
    cmd(f"npx hyperframes render --output {output} --fps 30 --quality standard", cwd=project_path)
    print(f"✅ 渲染完成:{output}")

Technical Analysis

The shared cmd() helper executes command strings with shell=True. The project_name and project values originate from command-line arguments and are used without shell-safe argument separation or restrictive validation.

In run_init(), the project name is interpolated directly into a shell command. Shell metacharacters in this value are consequently interpreted by the command shell rather than passed only as data to HyperFrames.

The code also constructs paths by joining PROJECT_ROOT with an unvalidated user value. Absolute paths can override the preceding root, while traversal components can resolve outside the intended workspace. In run_render(), this can select an unintended work ...[truncated 1383 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove shell=True and represent each command as an argument list:
    python
    def cmd(argv, cwd=None):
        result = subprocess.run(argv, cwd=cwd, shell=False, check=False)
        return result.returncode == 0
    
    cmd(
        ["npx", "hyperframes", "init", project_name, "--non-interactive"],
        cwd=PROJECT_ROOT,
    )
    
  • Apply a conservative project-name allowlist, such as letters, digits, underscores, and hyphens with a bounded length.
  • Resolve every project path before use and verify that it remains beneath the resolved project root:
    python
    root = PROJECT_ROOT.resolve()
    project_path = (root / project).resolve()
    if not project_path.is_relative_to(root):
        raise ValueError("Project path must remain inside the project root")
    
  • Reject absolute paths, traversal components, null bytes, and unexpected separators.
  • Pass render output paths as separate subprocess arguments rather than embedding them in a command string.
  • Use check=True or explicitly stop subsequent processing when initialization or rendering fails.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/run_heyvideogen.py:76
Finding

Indirect Shell Command Injection Through Generated Storyboard Content

Content
View full analysis

Vulnerability Details

File Location: scripts/run_heyvideogen.py, lines 76-112
Vulnerability Type: OS command injection through untrusted generated text
Risk Level: High

python
    # Step 2: TTS(复用 videogen harness)
    print("\n[2/4] 生成 TTS 配音...")
    narrations = [p.get("narration", "") for p in storyboard.get("panels", []) if p.get("narration")]
    script_text = " ".join(narrations)
    if script_text:
        tts_cmd = (
            f'python "{VIDEOS_SKILL}/scripts/v2/tts_harness.py" '
            f'"{script_text[:500]}" --output "{output_dir}"'
        )
        cmd(tts_cmd)
        print(f"   ✅ TTS 完成:{output_dir}/voiceover.mp3")
    else:
        print("   ⚠️  无旁白文本,跳过 TTS")

    # Step 3: 生成 AI 视频片段(Hailuo)
    print("\n[3/4] 生成 AI 视频片段...")
    panels = storyboard.get("panels", [])
    clips_ok, clips_fail = 0, 0
    for i, panel in enumerate(panels):
        prompt = panel.get("video_prompt", "")
        clip_path = clips_dir / f"clip_{i+1:02d}.mp4"
        if not prompt:
            print(f"   ⊝ clip_{i+1:02d}: 无 video_prompt,跳过")
            continue
        duration_sec = panel.get("duration", 6)
        hf_prompt = prompt.strip()
        if not hf_prompt:
            print(f"   ⊝ clip_{i+1:02d}: prompt 为空,跳过")
            continue
        gen_cmd = (
            f'python "{MINIMAX_SCRIPTS}/video/generate_video.py" '
            f'--mode t2v '
            f'--prompt "{hf_prompt}" '
            f'--duration {duration_sec} '
            f'--output "{clip_path}"'
        )
        print(f"\n   [{i+1}/{len(panels)}] 生成 clip_{i+1:02d}...")
        ok = cmd(gen_cmd)

Technical Analysis

Narration text, video prompts, and panel durations are read from the object returned by generate_storyboard(). Generated model output must be treated as untrusted because it can be influenced by the original topic and may contain quotation marks, shell su ...[truncated 1762 chars]

Remediation
View remediation

Remediation Suggestions

  • Eliminate shell command construction and pass all values as separate arguments:
    python
    cmd([
        sys.executable,
        str(VIDEOS_SKILL / "scripts/v2/tts_harness.py"),
        script_text[:500],
        "--output",
        str(output_dir),
    ])
    
    cmd([
        sys.executable,
        str(MINIMAX_SCRIPTS / "video/generate_video.py"),
        "--mode",
        "t2v",
        "--prompt",
        hf_prompt,
        "--duration",
        str(duration_sec),
        "--output",
        str(clip_path),
    ])
    
  • Ensure the command helper always uses shell=False.
  • Validate duration_sec as an integer within a documented safe range before invoking the child process.
  • Validate storyboard structure and field types against a strict schema.
  • Treat all model-generated content as untrusted, even when the initiating topic appears benign.
  • Avoid ad hoc shell escaping as the primary control; argument-array execution prevents shell interpretation by design.
  • Consider imposing reasonable text-length limits for resource control, while recognizing that length limits do not replace injection prevention.

T08 · Insecure Dependencies

Warning
Location
scripts/run_heyvideogen.py:38
Finding

Execution of Unpinned Third-Party Tooling and CDN Resources

Content
View full analysis

Vulnerability Details

File Location: scripts/run_heyvideogen.py, lines 38 and 135-138; templates/apple-style/index.html, line 231
Vulnerability Type: Third-party software supply-chain exposure
Risk Level: Medium

python
    rc = cmd(f"npx hyperframes init {project_name} --non-interactive", cwd=PROJECT_ROOT)
python
    ok = cmd(f"npx hyperframes lint", cwd=project_path)
    if not ok:
        print("⚠️  Lint 有警告,继续渲染...")
    cmd(f"npx hyperframes render --output {output} --fps 30 --quality standard", cwd=project_path)

The HTML template also loads executable JavaScript from a CDN without Subresource Integrity:

html
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>

Technical Analysis

The script invokes hyperframes through npx without an exact package declaration or project lockfile in the audited artifact. Depending on the runtime environment and npx behavior, a missing local package can be resolved and downloaded from the package registry at execution time. This means executable dependency content may differ from the content that was reviewed.

The template references a versioned GSAP CDN URL, which is safer than an unversioned URL, but it does not include a Subresource Integrity hash. Rendering therefore relies on the integrity and availability of the CDN response and its delivery path.

This finding does not establish that the current HyperFrames or GSAP packages are malicious. The risk arises because third-party executable content is not cryptographically locked to an audited artifact.

Attack Path

  1. The Skill is run in an environment where the required HyperFrames package is not already installed and locked locally.
  2. npx resolves the package from the configured registry and executes the retrieved code.
  3. If the registry account, package release, configured registry, or dependency chain is compromised, altered pack ...[truncated 745 chars]
Remediation
View remediation

Remediation Suggestions

  • Add a project manifest and lockfile that pin exact versions of HyperFrames and all transitive dependencies.
  • Install dependencies using a lockfile-enforcing, reproducible command and invoke the verified local executable rather than allowing npx to resolve an undeclared package dynamically.
  • Configure npx to refuse package installation at runtime where supported.
  • Review dependency provenance and use package-manager integrity verification in CI and deployment.
  • Vendor the required GSAP file locally after verifying its checksum, or add a published Subresource Integrity hash and an appropriate crossorigin attribute:
    html
    <script
      src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"
      integrity="sha384-VERIFIED_HASH_HERE"
      crossorigin="anonymous">
    </script>
    
  • Enforce an appropriate Content Security Policy in browser-based rendering where supported.
  • Cache and verify all rendering dependencies so that production execution does not depend on mutable external responses.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (34)

Vague Triggers

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger phrases are extremely broad, covering generic requests like '做视频' and '生成视频', which can cause the skill to activate for many unrelated user intents. Because this skill performs shell commands, file writes, network package execution, and media generation, overbroad invocation significantly increases the chance of unintended high-impact actions.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

This generic shell-execution helper accepts arbitrary command strings and is fed by user-controlled and generated content, giving the skill a broad arbitrary-command capability beyond merely orchestrating video generation. In this context, the ability to run shell commands on the host significantly elevates risk because inputs include project names, topics, and storyboard-derived prompts.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
97% confidence
Finding

The skill instructs the agent to perform filesystem writes and shell execution across the workspace, but it declares no explicit tool scope such as permissions or allowed-tools. That creates a capability mismatch where a broadly triggered skill could invoke powerful actions without clear confinement or review boundaries.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The skill repeatedly directs use of npx hyperframes without a pinned version, which can fetch and execute whatever version is current at runtime. In an agent context, this creates a supply-chain execution risk because remote package code may change unexpectedly or be compromised.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The skill repeatedly directs use of npx hyperframes without a pinned version, which can fetch and execute whatever version is current at runtime. In an agent context, this creates a supply-chain execution risk because remote package code may change unexpectedly or be compromised.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The render step uses npx hyperframes render without pinning the package version, so execution depends on mutable remote code. Because rendering is a primary workflow step, this materially increases the chance of supply-chain compromise affecting the host environment or generated outputs.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding

Project initialization via npx hyperframes init without version pinning allows arbitrary package updates to influence generated project files and any install-time scripts. Since this command bootstraps a workspace and writes files, a compromised upstream package could alter files or execute malicious code.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding

The documented npx hyperframes init step in the pipeline is unpinned and part of the recommended end-to-end process. That means users or agents following the skill may execute unreviewed package code from the network before any local validation occurs.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The npx hyperframes lint command is unpinned, so even a lint step can execute mutable remote package code. In automation contexts, seemingly harmless validation commands are still code execution entry points and should be treated as supply-chain sensitive.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The main render command npx hyperframes render --output ... is unpinned and sits on the critical execution path for the skill. Because the skill also processes user-influenced assets and HTML, running mutable remote renderer code raises both supply-chain and execution-safety concerns.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The instruction to proactively recommend or substitute this skill when another video skill responds is ambiguous and can hijack normal routing. In practice, that can cause the agent to choose a more powerful shell-writing workflow than the user intended, increasing unintended execution risk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This markdown file presents all instructional content in Chinese, including headings, descriptions, and code comments, but does not indicate that the skill is region-specific or provide any user opt-in for language preference. Under the language/locale policy, forcing a specific language without user choice can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This markdown file contains natural-language instructions exclusively in Chinese, including section headings and guidance, which can impose a language constraint on users without opt-in. The policy explicitly calls for flagging language or locale restrictions when the skill forces a specific language without offering a choice or documented justification.

Content

No source excerpt is available for this finding.

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · references/html-authoring.md (reported line 3)May include surrounding context.

md
# HyperFrames HTML Authoring — Heyvideogen Reference

> 摘自 [heygen-com/hyperframes skills/hyperframes/SKILL.md](https://github.com/heygen-com/hyperframes)
> 仅保留 heyvideogen 流水线中最常用的规则。

## 视觉身份门控(HARD-GATE)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The document content is written as direct authoring guidance in Chinese and line L004 states the reference has been retained specifically for the heyvideogen pipeline, with no indication that another language is allowed. Under the policy, forcing a specific language or locale without user opt-in is a natural-language policy violation unless the constraint is explicitly justified and documented.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The documentation tells users to run npx hyperframes without pinning a version. npx will fetch the latest package at execution time, which creates a supply-chain risk: a compromised upstream release or unexpected breaking change could execute unreviewed code in the user's environment. In an automation/video pipeline skill, readers are reasonably likely to copy-paste these commands, so the risk is practical rather than theoretical.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

This is the same unpinned npx hyperframes pattern on a second command. Because it separately instructs execution of remote package code without version locking, it independently exposes users to supply-chain compromise and non-deterministic behavior. The skill context increases concern because these are presented as routine validation steps that users may trust and run as-is.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The file's instructional content is written entirely in Chinese and provides no indication that users may choose another language or locale. Under the policy rule for natural-language constraints, this functions as a forced language choice rather than an opt-in or clearly justified region-specific requirement.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The documentation instructs users to run npx hyperframes tts ... without pinning a specific package version. npx may fetch and execute the latest package from the registry, which creates a supply-chain risk: a malicious or compromised upstream release could run arbitrary code on the operator's machine. In a video-generation skill that encourages CLI execution, this is more dangerous because users are likely to copy-paste these commands directly.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The command npx hyperframes tts --list also executes an unpinned package from the registry. Even though it appears read-only, the act of resolving and running the CLI can still execute attacker-controlled code if the package or dependency chain is compromised. Because this file is operational guidance, users may trust and run it without additional review.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The transcription example npx hyperframes transcribe ... has the same unpinned execution risk. If hyperframes or one of its transient dependencies is hijacked, the command could execute arbitrary code during what users expect to be a simple transcription step. Given this skill automates media pipelines and likely runs on creator workstations or build hosts, compromise could expose project files, credentials, or CI environments.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The script imports and executes code from sibling skills and shared script directories, effectively inheriting capabilities and trust assumptions outside this skill's own boundary. If those adjacent scripts are modified, compromised, or behave unexpectedly, this skill will execute them with the current user's privileges.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
98% confidence
Finding

The helper wraps subprocess.run with shell=True and is reused for commands that interpolate user-controlled or model-derived strings. This creates a command-injection sink where project names, prompts, or generated text can break quoting and execute arbitrary shell commands on the host.

Content

Scanner excerpt · scripts/run_heyvideogen.py (reported line 27)May include surrounding context.

python
def cmd(cmd: str, cwd=None, shell=True):
    print(f"\n>>> {cmd}")
    result = subprocess.run(cmd, cwd=cwd, shell=shell, capture_output=False)
    return result.returncode == 0

Rp1

Medium
Category
MCP Rug Pull
Confidence
84% confidence
Finding

Using npx hyperframes without pinning an exact package version makes execution depend on whatever version is currently resolved from the registry or local environment. That increases supply-chain risk and can unexpectedly run altered or compromised code during project initialization.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The init command interpolates the user-supplied project name directly into a shell command executed with shell=True. A crafted project name containing shell metacharacters can escape the intended argument and execute arbitrary commands on the machine.

Content

No source excerpt is available for this finding.