Back to skill

Security audit

Skill Veo3 Video Gen

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it claims, but its credential handling, dependency setup, and ffmpeg path handling need review before use.

Install only if you are comfortable sending prompts and reference images to Google's Gemini/Veo API and running local ffmpeg. Prefer GEMINI_API_KEY over --api-key, use a restricted API key, avoid sensitive reference images, use a private output directory, and review or pin dependencies before running.

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
scripts/generate_video.py:3
Finding

Unpinned Runtime Dependencies Create Supply-Chain Risk

Content
View full analysis
=3.10" # dependencies = [ # "google-genai>=1.0.0", # "pillow>=10.0.0", # ] # /// ``` ### Technical Analysis The inline dependency declaration specifies only minimum versions. It does not provide exact versions, upper bounds, package hashes, or an accompanying lockfile. Consequently, the documented `uv run` workflow may resolve and install future releases that were not present during the Skill's security review. Python packages execute code in the same process and under the same operating-system identity as the Skill. A compromised package release, compromised package index, or unexpectedly incompatible future release could therefore access the Gemini API key, prompts, reference images, generated media, and files available to the invoking user. The declared `pillow` dependency does not appear to be imported by the script. Keeping an unused dependency unnecessarily expands the supply-chain and installation attack surface. This finding does not establish that the currently available packages are malicious. The issue is that future dependency resolution is mutable and is not reproducibly constrained to reviewed artifacts. ### Attack Path 1. An attacker compromises a future release of `google-genai` or `pillow`, the configured package repository, or an associated publishing account. 2. A user invokes the documented `uv run scripts/generate_video.py ...` command in an environment that has not already locked the dependencies. 3. The resolver selects and installs the compromised release because it satisfies the broad `>=` constraint. 4. Malicious package code executes with the privileges of the user running the Skill. 5. The dependency can read process data, including the Gemini API key and generation inputs, and access fi ...[truncated 633 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_video.py:243
Finding

Gemini API Key Can Be Exposed Through Command-Line Arguments

Content
View full analysis
str | None: if provided_key: return provided_key return os.environ.get("GEMINI_API_KEY") ``` ```python parser.add_argument( "--api-key", "-k", help="API key (overrides GEMINI_API_KEY)", ) ``` ```python api_key = get_api_key(args.api_key) if not api_key: print("Error: No API key provided.", file=sys.stderr) print("Set GEMINI_API_KEY or pass --api-key", file=sys.stderr) sys.exit(1) ``` ```python client = genai.Client(api_key=api_key) ``` ### Technical Analysis The Skill permits a Gemini API key to be supplied directly through `--api-key` or `-k`. Command-line arguments are commonly exposed through shell history, process inspection utilities, process accounting, debugging output, job runners, audit logs, and orchestration telemetry. Passing the credential to the official Google SDK is necessary for the declared functionality. The vulnerable behavior is accepting the credential as plaintext command-line metadata rather than restricting secret intake to a protected environment variable, secret file descriptor, secret manager, or hidden interactive prompt. The script does not explicitly print the key. Nevertheless, once supplied as an argument, the secret may be recorded or visible outside the script before `argparse` processes it. ### Attack Path 1. A user invokes the supported interface, for example: ```bash python scripts/generate_video.py --api-key SECRET --prompt "..." --filename out.mp4 ``` 2. The command is stored in shell history, captured by a job runner, or exposed in the process argument list. 3. A local user, administrator, monitoring agent, or party with access to collected command telemetry retrieves the plaintex ...[truncated 879 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_video.py:137
Finding

Unescaped Paths in ffmpeg Concat Manifest Permit Directive Injection

Content
View full analysis
None: require_bin("ffmpeg") out_path.parent.mkdir(parents=True, exist_ok=True) # Create concat list file. lst = out_path.with_suffix(out_path.suffix + ".concat.txt") lines = [f"file '{p.as_posix()}'" for p in inputs] lst.write_text("\n".join(lines) + "\n", encoding="utf-8") cmd = [ "ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", str(lst), "-c", "copy", str(out_path), ] p = subprocess.run(cmd, capture_output=True, text=True) ``` ### Technical Analysis The output filename is user-controlled through `--filename`. Segment paths are derived from that filename and then embedded directly into an ffmpeg concat-demuxer manifest: ```python lines = [f"file '{p.as_posix()}'" for p in inputs] ``` The code does not reject or escape single quotes, backslashes, carriage returns, or newline characters according to ffmpeg concat-file syntax. A crafted filename can therefore terminate the quoted path or introduce additional manifest lines and directives. The invocation also uses `-safe 0`, disabling the concat demuxer's normal safe-path restrictions. This is not shell-command injection because ffmpeg is executed with an argument list and `shell=False`. The risk instead exists inside the ffmpeg manifest parser: attacker-controlled path text can alter the data interpreted by ffmpeg. The manifest is created at a predictable path next to the requested output and is never removed. This leaves local path metadata behind and can also expose the operation to file-replacement or race conditions when the output directory is writable by another user. ### Attack Pa ...[truncated 1703 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill exposes capabilities involving environment access, file I/O, network access, and shell execution, but it does not declare any explicit tool scope or permissions. This weakens least-privilege controls and makes it harder for users or orchestrators to understand and constrain what the skill can do before execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill references Gemini API usage and reference-image inputs, but it does not clearly disclose that prompts and uploaded images are sent to an external third-party service. Users may unknowingly transmit confidential text, product assets, or personal data off-system, creating privacy, compliance, and data-handling risks.

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

python
def require_bin(name: str) -> None:
    if subprocess.run(["bash", "-lc", f"command -v {shlex.quote(name)}"], capture_output=True).returncode != 0:
        raise RuntimeError(f"Required binary not found on PATH: {name}")

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

python
"2",
        str(out_png),
    ]
    p = subprocess.run(cmd, capture_output=True, text=True)
    if p.returncode != 0:
        raise RuntimeError(f"ffmpeg last-frame extract failed: {p.stderr[-2000:]}")
    return out_png

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

python
"2",
        str(out_png),
    ]
    p = subprocess.run(cmd, capture_output=True, text=True)
    if p.returncode != 0:
        raise RuntimeError(f"ffmpeg last-frame extract failed: {p.stderr[-2000:]}")
    return out_png

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

python
"192k",
            str(out_path),
        ]
        p2 = subprocess.run(cmd2, capture_output=True, text=True)
        if p2.returncode != 0:
            raise RuntimeError(
                "ffmpeg concat failed.\n"

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The skill documentation tells users it generates videos but does not clearly warn that MP4 outputs are written to local disk and that intermediate segment files may persist when stitching is enabled. This can lead to unintentional storage of sensitive or regulated content on the local filesystem, especially in shared or ephemeral environments.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.