Back to skill

Security audit

video-understanding

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a legitimate Gemini video-analysis skill, but it needs review because it can fetch arbitrary video URLs from the host network and upload video content to Google using local credentials.

Install only in an environment where users are trusted to choose video sources, or where network egress blocks internal, metadata, loopback, private, and redirected destinations. Treat all analyzed videos and prompts as sent to Google Gemini, avoid signed URLs or confidential recordings unless authorized, and use the cache/history flags only when retention is intended.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/analyze_video.py:51
Finding

Unrestricted Video URL Fetching Enables Server-Side Request Forgery

Content
View full analysis

Vulnerability Details

File Location: scripts/analyze_video.py:51-58, scripts/analyze_video.py:258-270, and scripts/analyze_video.py:762-776
Vulnerability Type: Server-Side Request Forgery and insecure HTTP transport
Risk Level: Medium

Vulnerable Code

python
def validate_source(source: str) -> None:
    if local_video_path(source):
        return
    parsed = urlsplit(source)
    if parsed.scheme not in ("https", "http") or not parsed.hostname or parsed.username or parsed.password:
        raise ValueError("Use an existing local video or a credential-free HTTP(S) URL")
    sensitive = {"token", "access_token", "api_key", "apikey", "password", "signature", "sig", "authorization", "key"}
    query_keys = {key.lower() for key in parse_qs(parsed.query, keep_blank_values=True)}
    if query_keys & sensitive or any(key.startswith(("x-amz-", "x-goog-")) for key in query_keys):
        raise ValueError("Do not place credentials in command arguments; use an authorized local download")
python
def download_video(url: str, output_path: str, max_size_mb: int = 500) -> str:
    """Download video using yt-dlp. Returns the actual output file path."""
    cmd = [
        "yt-dlp", "--ignore-config",
        "-f", "bestvideo+bestaudio/best",
        "--merge-output-format", "mp4",
        "--remux-video", "mp4",
        "--no-playlist",
        "--max-filesize", f"{max_size_mb}M",
        "-o", output_path,
        "--", url,
    ]
    print("Downloading video source...", file=sys.stderr)
    result = subprocess.run(cmd, capture_output=True, text=True)
python
# Download for non-YouTube
tmp_dir = None
if args.download_only and args.output:
    video_path = args.output
else:
    tmp_dir = tempfile.mkdtemp()
    video_path = os.path.join(tmp_dir, "video.%(ext)s")

try:
    video_path = download_video(args.url, video_path, args.max_size)

    if args.download_only:
        print("Saved requested output", file=sys.stderr)
        return

 
...[truncated 2866 chars]
Remediation
View remediation

Remediation Suggestions

  1. Require HTTPS for remote sources by default. If HTTP support is operationally necessary, make it an explicit privileged option and warn that transport integrity is unavailable.
  2. Resolve destination hostnames and reject all loopback, private, link-local, multicast, unspecified, reserved, and cloud metadata addresses for both IPv4 and IPv6.
  3. Apply the same checks after every redirect and to all extractor, manifest, segment, and CDN requests. Initial URL validation alone is insufficient.
  4. Protect against DNS rebinding by binding validated resolutions to actual outbound connections where possible.
  5. Prefer a configurable allowlist of trusted video providers when processing requests from untrusted users.
  6. Run yt-dlp, ffmpeg, and related child processes in an isolated sandbox with no access to internal networks, metadata services, or unnecessary filesystem resources.
  7. Enforce network egress controls outside the process, such as a restricted proxy, firewall rules, or an isolated network namespace. This should be the primary SSRF boundary.
  8. Prevent content obtained from private or unapproved destinations from being uploaded to Gemini.
  9. Add tests covering direct and redirected requests to loopback, RFC1918, link-local, IPv6 local, reserved, and cloud metadata addresses.
  10. Retain the existing privacy documentation, but do not treat documentation or user authorization as a substitute for destination-level network controls.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (7)

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/analyze_video.py (reported line 338)May include surrounding context.

python
"""
    if question:
        prompt += QUESTION_ADDENDUM.format(question=question)
    return prompt


def is_transient_model_error(exc: Exception) -> bool:

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill invokes shell commands, accesses environment credentials, reads and writes local files, and performs network operations, but it does not declare any explicit tool scope or permission boundaries. That makes the effective privilege surface opaque to the host and increases the chance the skill is invoked with broader capabilities than intended, especially given it can download arbitrary HTTPS video sources and upload local content to a cloud provider.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill advertises activation for broad phrases like casual requests to 'watch or react,' which can cause it to trigger on common conversational input without the user clearly intending cloud video analysis. In this skill's context, accidental invocation is more dangerous because it may lead to network fetching of arbitrary URLs, local file handling, or cloud upload of video content unless the surrounding agent reliably enforces the documented consent step.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script uploads potentially sensitive local or downloaded video content to Google Gemini, but the module-level description does not clearly warn about privacy and third-party data transfer implications. In a skill environment handling arbitrary user videos, insufficient disclosure increases the risk of unintentionally exfiltrating confidential visual, audio, or on-screen information to a cloud provider.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill automatically reads API credentials from unrelated local secret and config files outside the explicit user input flow. In an agent-skill context, this broadens access to local sensitive material and can cause the skill to use ambient credentials without clear user awareness or consent, which weakens least-privilege boundaries.

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/analyze_video.py (reported line 270)May include surrounding context.

python
"--", url,
    ]
    print("Downloading video source...", file=sys.stderr)
    result = subprocess.run(cmd, capture_output=True, text=True)
    if result.returncode != 0:
        raise RuntimeError(f"Video download failed (exit {result.returncode}); source details suppressed")

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The top-level docstring states 'Download a video and analyze it with Google Gemini,' which implies downloading is intrinsic to operation. In reality, the script has alternate paths for direct local-file upload and direct YouTube URL analysis with no download step, so the documentation misstates the actual behavior.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.