Back to skill

Security audit

Video Generation (t2v & i2v)

Security checks for vulnerabilities and agentic risk

Overview

The skill broadly matches AI video generation, but it handles local images and environment-file secrets in ways that need user review before installation.

Install only if you are comfortable sending prompts and selected images to external services. Use a dedicated directory without unrelated .env secrets, avoid running from private project roots, prefer narrowly scoped API keys, and consider pinning or locally vendoring the inference.sh CLI before 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)

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding
Unpinned Python and CLI Dependencies Create Supply-Chain Exposure<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:1-5`; installation guidance also appears in `README.md:14-24` and `SKILL.md:17-20` **Vulnerability Type**: Unconstrained third-party dependency installation **Risk Level**: Medium ### Vulnerable Code ```text httpx>=0.27.0 # Note: This skill also requires the inference.sh CLI to be installed separately. # Install with: npm install -g @inference.sh/cli # Visit https://inference.sh for more information. ``` The documented CLI installation is also unpinned: ```bash npm install -g @inference.sh/cli ``` ### Technical Analysis The Python dependency accepts any `httpx` version at or above `0.27.0`, while the external `@inference.sh/cli` package is installed globally without an exact version or integrity constraint. The repository contains no reviewed lockfile or package hashes. Both generation scripts subsequently execute `inference.sh` as a local program. Consequently, the effective code executed by the skill depends on whichever package version is available when installation occurs, rather than a version reviewed together with this project. This does not establish that the current upstream packages are malicious. It creates a supply-chain weakness under which an upstream compromise, malicious future release, package ownership transfer, or incompatible update could introduce unreviewed behavior. ### Attack Path 1. An attacker compromises an upstream package publication account or causes a malicious version to be published. 2. A user follows the documented installation instructions without specifying a version. 3. The package manager resolves and installs the attacker-controlled or otherwise unreviewed release. 4. The user invokes either video-generation script. 5. The scripts execute the globally resolved `inference.sh` binary with the privileges and inherited environment of the user. 6. The compromised dependency can access data and resources available to that process, including prompts ...[truncated 601 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin Python packages to reviewed exact versions, for example: ```text httpx==<reviewed-version> ``` 2. Generate and commit a lockfile containing cryptographic hashes, such as a hash-checked `requirements.txt` produced through `pip-tools`. 3. Pin the CLI to a reviewed exact version: ```bash npm install --global @inference.sh/cli@<reviewed-version> ``` 4. Prefer a project-local CLI installation over a global installation and invoke the known local binary explicitly. 5. Document the canonical package ecosystem and remove ambiguous alternative installation commands unless both packages are independently verified. 6. Use package-manager integrity controls, dependency scanning, and a controlled update process before changing pinned versions. 7. Run the external CLI in a sandbox with a minimal environment and only the filesystem/network access required for video generation. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/image_to_video.py:15
Finding
External CLI Inherits All Variables Loaded from Project and Working-Directory Environment Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/image_to_video.py:15-43, 194-201`; equivalent behavior in `scripts/text_to_video.py:12-40, 116-123` **Vulnerability Type**: Excessive environment-variable exposure to a third-party subprocess **Risk Level**: Medium ### Vulnerable Code The image workflow loads every valid entry from an environment file: ```python def _load_env_file(path: Path) -> None: """Load environment variables from .env file.""" if not path.exists() or not path.is_file(): return for raw_line in path.read_text(encoding="utf-8").splitlines(): line = raw_line.strip() if not line or line.startswith("#") or "=" not in line: continue key, value = line.split("=", 1) key = key.strip() value = value.strip() if not key: continue if len(value) >= 2 and value[0] == value[-1] and value[0] in ("'", '"'): value = value[1:-1] os.environ.setdefault(key, value) def _load_default_envs(env_file: str) -> None: """Load default environment files.""" if env_file: _load_env_file(Path(env_file).expanduser()) return skill_root = Path(__file__).resolve().parent.parent _load_env_file(skill_root / ".env") _load_env_file(Path.cwd() / ".env") ``` The external CLI is then executed without a restricted environment: ```python result = subprocess.run( cmd, capture_output=True, text=True, encoding='utf-8', errors='replace', timeout=timeout ) ``` The text workflow contains the same environment-loading pattern and also invokes `subprocess.run` without an explicit `env` argument. ### Technical Analysis The loaders do not allowlist variables required by the video service. Instead, they copy every key from the selected `.env`, the skill-root `.env`, and the current working directory's `.env` into `os.environ`. Python subprocesses inherit the parent process environment by default when ...[truncated 1847 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Stop importing every entry from the current working directory's `.env` by default. 2. Define an explicit allowlist of variables required by each workflow, such as only the relevant inference-service credential and `IMGBB_API_KEY`. 3. Construct a minimal subprocess environment rather than inheriting `os.environ`: ```python child_env = { "PATH": os.environ.get("PATH", ""), "HOME": os.environ.get("HOME", ""), "REQUIRED_INFERENCE_KEY": os.environ["REQUIRED_INFERENCE_KEY"], } subprocess.run(cmd, env=child_env, ...) ``` 4. Resolve and invoke a trusted, project-local CLI path rather than relying on any matching executable in `PATH`. 5. Separate credentials by purpose and avoid placing unrelated secrets in a shared `.env`. 6. Document exactly which variables are read and transmitted to child processes. 7. Run the CLI in a sandbox or container with restricted filesystem and network access. 8. Add tests confirming that unrelated sentinel variables are absent from the child process environment. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/image_to_video.py:101
Finding
ImgBB API Credential Is Embedded in the Request URL<![CDATA[ ## Vulnerability Details **File Location**: `scripts/image_to_video.py:101-117` **Vulnerability Type**: Sensitive credential included in a URL query string **Risk Level**: Low ### Vulnerable Code ```python def upload_to_imgbb(image_path: Path, api_key: str = None) -> str: """Upload image to ImgBB image hosting service. Args: image_path: Image file path api_key: ImgBB API Key (required) Returns: Image URL """ if not api_key: raise ValueError("ImgBB API key is required. Provide it via --api-token or IMGBB_API_KEY environment variable.") url = f"https://api.imgbb.com/1/upload?key={api_key}" with image_path.open("rb") as f: files = {"image": f} response = httpx.post(url, files=files, timeout=30.0) ``` ### Technical Analysis The ImgBB API key is interpolated directly into the URL query string. TLS protects the request in transit from ordinary passive observers, but URL query strings are commonly recorded by application diagnostics, HTTP instrumentation, reverse proxies, endpoint monitoring, exception reporting, and debugging systems. The script does not directly print this URL, so credential disclosure is not guaranteed during normal execution. However, placing secrets in URLs increases their exposure compared with an authorization header or request body and makes accidental logging more likely. ### Attack Path 1. A user supplies an ImgBB API key through `--api-token` or `IMGBB_API_KEY`. 2. The script inserts the complete key into the upload URL. 3. HTTP debugging, proxy logging, tracing, exception telemetry, or endpoint instrumentation records the requested URL. 4. An actor with access to those logs retrieves the query parameter. 5. The actor uses the recovered key against the ImgBB API within the permissions and quotas associated with that credential. This path depends on URL logging or telemetry being enabled; the audited code does not itself write the URL to its norm ...[truncated 340 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. If the ImgBB API supports it, transmit the credential in an authorization header rather than the URL. 2. If the service requires the key as a parameter, prefer a POST body parameter when supported: ```python response = httpx.post( "https://api.imgbb.com/1/upload", data={"key": api_key}, files=files, timeout=30.0, ) ``` 3. Configure HTTP clients, proxies, tracing systems, and error reporters to redact the `key` parameter. 4. Never include the complete request URL in returned errors or debug output. 5. Use a narrowly scoped key where the service supports scoping, apply usage monitoring, and rotate the key after suspected logging or disclosure. 6. Prefer environment-based or protected secret-store input over command-line `--api-token`, because command-line arguments may also be visible to local process inspection and shell history. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • 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 (30)

Credential Access

High
Category
Privilege Escalation
Content
3. Configure environment variables:
```bash
cp .env.example .env
# Edit .env with your API keys
```
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The code aligns with part of the description: it generates AI videos from text prompts, supports selecting among named models, saves outputs locally, and loads environment variables. However, the supplied code chunk does not implement image-to-video or image animation functionality, which is explicitly claimed in the declared description. There are no obviously undeclared dangerous capabilities; the mismatch is that the description overstates the implemented functionality in this chunk. Because evaluation is based on the supplied code chunk, this should be flagged as a description/behavior mismatch.

Credential Access

High
Category
Privilege Escalation
Content
def _load_env_file(path: Path) -> None:
    """Load environment variables from .env file."""
    if not path.exists() or not path.is_file():
        return
    for raw_line in path.read_text(encoding="utf-8").splitlines():
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
def _load_env_file(path: Path) -> None:
    """Load environment variables from .env file."""
    if not path.exists() or not path.is_file():
        return
    for raw_line in path.read_text(encoding="utf-8").splitlines():
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
def _load_env_file(path: Path) -> None:
    """Load environment variables from .env file."""
    if not path.exists() or not path.is_file():
        return
    for raw_line in path.read_text(encoding="utf-8").splitlines():
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
def _load_env_file(path: Path) -> None:
    """Load environment variables from .env file."""
    if not path.exists() or not path.is_file():
        return
    for raw_line in path.read_text(encoding="utf-8").splitlines():
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
_load_env_file(Path(env_file).expanduser())
        return
    skill_root = Path(__file__).resolve().parent.parent
    _load_env_file(skill_root / ".env")
    _load_env_file(Path.cwd() / ".env")
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
_load_env_file(Path(env_file).expanduser())
        return
    skill_root = Path(__file__).resolve().parent.parent
    _load_env_file(skill_root / ".env")
    _load_env_file(Path.cwd() / ".env")
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
_load_env_file(Path(env_file).expanduser())
        return
    skill_root = Path(__file__).resolve().parent.parent
    _load_env_file(skill_root / ".env")
    _load_env_file(Path.cwd() / ".env")
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
return
    skill_root = Path(__file__).resolve().parent.parent
    _load_env_file(skill_root / ".env")
    _load_env_file(Path.cwd() / ".env")


def _build_parser() -> argparse.ArgumentParser:
Confidence
90% confidence
Finding
Automatically importing variables from the current working directory's .env file is dangerous in agent environments because CWD may be influenced by the caller, workspace contents, or untrusted repositories. An attacker can plant a .env to override endpoints, proxies, or tokens used by the external video-generation CLI, potentially redirecting requests or causing credential misuse.

Credential Access

High
Category
Privilege Escalation
Content
parser.add_argument("--fps", type=int, default=24, help="Frames per second (default 24).")
    parser.add_argument("--save-dir", default="", help="Directory for saved videos (default: ./outputs/videos).")
    parser.add_argument("--timeout", type=int, default=600, help="Request timeout in seconds.")
    parser.add_argument("--env-file", default="", help="Optional .env file path.")
    parser.add_argument("--dry-run", action="store_true", help="Print request and exit.")
    return parser
Confidence
87% confidence
Finding
Accepting an arbitrary --env-file path widens the trust boundary and lets callers inject environment variables into the process from any readable file formatted like a .env. In an agent setting, this can be used to alter authentication, networking, or provider configuration for the downstream CLI, with possible secret exfiltration or request redirection.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The README explicitly states that local images are automatically uploaded to cloud storage for image-to-video generation, but it does not provide a clear warning about data transmission, retention, or privacy implications. In a skill that processes user-supplied local media, this can lead to unintentional disclosure of sensitive images or metadata to third-party services.

Lp3

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding
The skill invokes Python scripts, requires a globally installed CLI, uses networked model APIs, reads local files, and may access environment variables for API keys, yet it declares no explicit tool scope or permissions. This weakens sandboxing and review controls, increasing the chance the agent can perform broader file, shell, network, or env access than users or operators expect.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The skill uses broad trigger phrases like general 'video creation' and 'AI video' requests, which can cause over-selection in contexts where the user did not intend to invoke a shell/network-enabled skill. In an agent system, loose routing increases the chance of unnecessary execution of a capability that can access local files, external services, and API-backed generation tools.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The skill instructs users to upload local images to third-party services such as SM.MS or ImgBB without an explicit warning that local content will leave the system and be disclosed to external providers. In this skill's context, uploaded images may contain sensitive personal, corporate, or regulated data, making silent exfiltration to public or semi-public hosting particularly risky.

External Transmission

Medium
Category
Data Exfiltration
Content
2. Generate video using the image URL
3. Download and save locally

**IMPORTANT**: For ImgBB, you must provide an API token via `--api-token` or set `IMGBB_API_KEY` environment variable. Get your free API key at https://api.imgbb.com/

Output JSON example:
Confidence
93% confidence
Finding
The skill explicitly directs use of an external endpoint and API key for ImgBB, which confirms external transmission of user-supplied content and secrets. While external API use is expected for this kind of skill, it is still security-relevant because it transmits data off-host and encourages environment-based secret handling without clearly scoped protections.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The argument help explicitly requires the video description to be 'in English,' which imposes a language constraint on users. The file does not offer opt-in language selection or explain why English is required, so this is a natural-language policy concern.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The script uploads user-provided local images to public third-party hosting services before generation, which creates an undisclosed data exfiltration path for potentially sensitive files. In the context of a video-generation skill, image-to-video is expected, but public reposting of source images to unrelated hosts is not necessary or obvious to the user and increases privacy and retention risk.

External Transmission

Medium
Category
Data Exfiltration
Content
if not api_key:
        raise ValueError("ImgBB API key is required. Provide it via --api-token or IMGBB_API_KEY environment variable.")

    url = f"https://api.imgbb.com/1/upload?key={api_key}"

    with image_path.open("rb") as f:
        files = {"image": f}
Confidence
94% confidence
Finding
This code transmits local image content to an external service, and the API key is placed in the URL query string, which may be logged by intermediaries, client tooling, or server access logs. Combined with the image upload itself, this creates both data exposure and secret leakage risks.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
Normal execution uploads the input image externally without any explicit runtime warning, consent prompt, or disclosure in the result payload before transmission occurs. This can surprise users and leak private content, especially when local images may contain personal, confidential, or regulated information.

Context-Inappropriate Capability

Medium
Confidence
76% confidence
Finding
The manifest presents the skill as an AI video generation toolkit using multiple models, but this implementation depends on spawning an external command rather than directly invoking a documented API within the skill. Executing subprocesses is a broader capability than the manifest communicates and can have security implications distinct from ordinary network-based generation.

Context-Inappropriate Capability

Medium
Confidence
86% confidence
Finding
The script will load environment variables from an arbitrary path supplied by --env-file and also implicitly from .env files in the skill root and current working directory. In an agent or multi-tenant context, this can import attacker-controlled configuration, including API keys, endpoints, or proxy settings, altering downstream behavior or causing secrets to be sent to unintended services.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The CLI help text explicitly says the prompt must be a "Video description in English." This imposes a language restriction as a natural-language policy choice, and the file does not provide user opt-in, alternatives, or a documented regional/compliance justification.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The manifest describes a video-generation toolkit, but this implementation delegates work by spawning the external `inference.sh` program. Launching subprocesses is a stronger capability than the manifest communicates and is not obviously justified from the manifest text alone, which frames the skill around model-based video generation rather than host command execution.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
return {"ok": True, "dry_run": True}

    # Execute command
    result = subprocess.run(
        cmd,
        capture_output=True,
        text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Static analysis

No suspicious patterns detected.