Back to skill

Security audit

Venice AI Media

Security checks for vulnerabilities and agentic risk

Overview

This Venice media skill is mostly coherent, but its URL-based upscaler can fetch arbitrary internal or large URLs from the user's machine and forward them to Venice.

Install only if you trust the workflows and can control the inputs. Prefer local image files over --url, avoid internal or private URLs, protect the Clawdbot config file that stores the API key, avoid --embed-exif for sensitive prompts, and treat --no-validate as an advanced override that may affect cost, behavior, and safety filtering.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/venice-upscale.py:113
Finding

Unrestricted URL Fetching Enables Server-Side Request Forgery and Data Disclosure

Content
View full analysis
str: """Download an HTTP(S) URL and return as raw base64 string.""" req = urllib.request.Request(url, headers={"User-Agent": USER_AGENT}) with urllib.request.urlopen(req, timeout=60) as resp: data = resp.read() return base64.b64encode(data).decode("ascii") def upscale_image_from_url( api_key: str, image_url: str, scale: int = 2, enhance: bool = False, enhance_prompt: str | None = None, enhance_creativity: float | None = None, replication: float | None = None, ) -> bytes: """ Upscale an image via Venice API using a URL or base64 data URL. HTTP(S) URLs are downloaded and converted to base64 first. Returns raw image bytes. """ # API requires base64, not HTTP URLs if image_url.startswith(("http://", "https://")): image_url = _fetch_url_as_base64(image_url) ``` ### Technical Analysis The `--url` argument is treated as a trusted network location after checking only that its textual value begins with `http://` or `https://`. The process then fetches the supplied address from its own network context. No controls prevent requests to: - Loopback addresses such as `127.0.0.1` or `[::1]` - RFC 1918 private networks - Link-local addresses - Cloud instance metadata services - Internal DNS names - Reserved or otherwise non-public address ranges `urllib.request.urlopen` follows HTTP redirects by default, but redirect destinations are not revalidated. An initially public URL can consequently redirect to an internal address. The response is also consumed with an unrestricted `resp.read()`. There is no `Content-Length` limit, streaming limit, image MIME-type verification, ...[truncated 2191 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/venice-image.py:178
Finding

Unescaped Prompt and Output Path Permit Stored HTML Injection in Generated Gallery

Content
View full analysis
None: """Generate HTML thumbnail gallery.""" thumbs = "\n".join( f""" {it['prompt'][:100]}{'...' if len(it['prompt']) > 100 else ''} """ for it in items ) html = f""" Venice Image Gallery :root {{ color-scheme: dark; }} body {{ margin: 24px; font: 14px/1.4 ui-sans-serif, system-ui; background: #0b0f14; color: #e8edf2; }} h1 {{ font-size: 18px; margin: 0 0 16px; }} .grid {{ display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; }} figure {{ margin: 0; padding: 12px; border: 1px solid #1e2a36; border-radius: 14px; background: #0f1620; }} img {{ width: 100%; height: auto; border-radius: 10px; display: block; }} figcaption {{ margin-top: 10px; color: #b7c2cc; font-size: 13px; }} code {{ color: #9cd1ff; }}

Venice Image Gallery

Output: {out_dir.as_posix()}

{thumbs}
""" (out_dir / "index.html").write_text(html, encoding="utf-8") ``` ### Technical Analysis The gallery generator directly interpolates dynamic values into HTML without context-appropriate escaping: - `it['prompt']` is inserted into an HTML element body. - `out_dir.as_posix()` is inserted into an HTML element body. - `it['file']` is inserted into quoted HTML attributes. The prompt and output directory can be supplied through command-line arguments. A prompt containing HTML markup can close the existing `figcaption` element and inject arbitrary elements or event handlers. Truncating ...[truncated 1992 chars]
Remediation
View remediation
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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (24)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code accurately supports one subset of the description: text-to-image generation via the Venice image API, with options like style presets, safe mode, EXIF embedding, and batch variants. However, the declared description claims broader capabilities—editing images, upscaling images, and creating videos from images—that are absent from this code chunk. There are no signs of video endpoints, upload/edit flows, or upscaling operations. Since the declared purpose materially overstates the implemented capabilities in the provided code, this should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The supplied code only implements Venice AI video-related operations: converting local image/audio inputs to data URLs, requesting a video price quote, queuing an image-to-video job, polling for completion, downloading the resulting video, listing video models, and optionally deleting/cleaning up generated media on the server. It does not implement image generation, image editing, or image upscaling, which are prominently included in the declared description. While some undeclared items like quoting and cleanup are ancillary to the primary video workflow, the main mismatch is that the description presents a broad multimodal image/video skill, whereas this code chunk is narrowly an image-to-video client. Therefore the description does not accurately represent this code chunk's actual behavior.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
89% confidence
Finding

The skill promotes a --no-validate option that skips model validation for new or beta models. Disabling validation weakens safety and integrity checks, increasing the chance of invoking unsupported, unintended, or policy-bypassing endpoints and making misuse easier in an uncensored external service context.

Content

Scanner excerpt · SKILL.md (reported line 119)May include surrounding context.

python3 {baseDir}/scripts/venice-image.py --prompt "abstract art" --out-dir /tmp/venice python3 {baseDir}/scripts/venice-image.py --list-models python3 {baseDir}/scripts/venice-image.py --list-styles python3 {baseDir}/scripts/venice-image.py --prompt "fantasy" --model flux-2-pro --no-validate python3 {baseDir}/scripts/venice-image.py --prompt "photo" --style-preset "Cinematic" --embed-exif

text

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
91% confidence
Finding

The documented key flags include --no-validate, explicitly normalizing the bypass of model checks. In a skill that performs networked generation against changing external models, encouraging validation bypass undermines guardrails and can lead to calls against unreviewed models with different safety, cost, or data-handling characteristics.

Content

Scanner excerpt · SKILL.md (reported line 123)May include surrounding context.

python3 {baseDir}/scripts/venice-image.py --prompt "photo" --style-preset "Cinematic" --embed-exif

text

**Key flags:** `--prompt`, `--model` (default: flux-2-max), `--count` (uses efficient batch API for same prompt), `--width`, `--height`, `--format` (webp/png/jpeg), `--resolution` (1K/2K/4K), `--aspect-ratio`, `--negative-prompt`, `--style-preset` (use `--list-styles` to see options), `--cfg-scale` (prompt adherence 0-20, default 7.5), `--seed` (for reproducible results), `--safe-mode` (disabled by default for uncensored output), `--hide-watermark` (only use if explicitly requested - watermark supports Venice), `--embed-exif` (embed prompt in image metadata), `--lora-strength` (0-100 for applicable models), `--steps` (inference steps, model-dependent), `--enable-web-search`, `--no-validate` (skip model check for new/beta models)

## Image Upscale

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Allowing --no-validate in video generation is especially risky because video jobs may be long-running, higher-cost, and retain server-side state. Skipping validation can expose users to unintended charges, unsupported parameters, or unsafe model behavior while also complicating cleanup of remote artifacts.

Content

Scanner excerpt · SKILL.md (reported line 169)May include surrounding context.

python3 {baseDir}/scripts/venice-video.py --complete <queue_id> --model

text

**Key flags:** `--image` (required for generation), `--prompt` (required for generation), `--model` (default: wan-2.6-image-to-video), `--duration` (model-dependent, see --list-models), `--resolution` (480p/720p/1080p), `--aspect-ratio`, `--audio`/`--no-audio`, `--skip-audio-param`, `--quote` (price estimate), `--timeout`, `--poll-interval`, `--no-delete` (keep server media), `--complete` (cleanup previously downloaded video), `--no-validate` (skip model check)

**Progress:** During generation, the script shows estimated progress based on Venice's average execution time.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
91% confidence
Finding

The tips section actively advises users to use --no-validate for beta or new models, which elevates the issue from a hidden option to endorsed behavior. That guidance increases the likelihood that operators will routinely bypass checks designed to constrain unexpected API behavior and safety differences.

Content

Scanner excerpt · SKILL.md (reported line 186)May include surrounding context.

md
**Tips:**

- Use `--no-validate` for new or beta models not yet in the model list
- Use `--quote` for video to check pricing before generation
- Safe mode is disabled by default (Venice is an uncensored API)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
88% confidence
Finding

Troubleshooting guidance that suggests using --no-validate when a model is not found trains users to bypass validation as a first-line response rather than confirming model legitimacy. This can normalize insecure operation and lead to accidental use of invalid, mistyped, or unapproved models.

Content

Scanner excerpt · SKILL.md (reported line 211)May include surrounding context.

md
**"Model not found"**

- Run `--list-models` to see available models
- Use `--no-validate` for new/beta models

**Video stuck/timeout**

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/venice-image.py (reported line 225)May include surrounding context.

python
ap.add_argument("--resolution", help="Resolution preset (1K, 2K, 4K)")
    ap.add_argument("--aspect-ratio", help="Aspect ratio (1:1, 16:9, etc.)")
    ap.add_argument("--safe-mode", action="store_true", default=False, help="Blur adult content (default: false)")
    ap.add_argument("--no-safe-mode", action="store_false", dest="safe_mode", help="Disable safe mode")
    ap.add_argument("--hide-watermark", action="store_true", help="Remove Venice watermark")
    ap.add_argument("--embed-exif", action="store_true", help="Embed prompt info in image EXIF metadata")
    ap.add_argument("--lora-strength", type=int, help="LoRA strength 0-100 for applicable models")

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/venice-image.py (reported line 234)May include surrounding context.

python
ap.add_argument("--out-dir", help="Output directory (default: auto-generated)")
    ap.add_argument("--list-models", action="store_true", help="List available image models and exit")
    ap.add_argument("--list-styles", action="store_true", help="List available style presets and exit")
    ap.add_argument("--no-validate", action="store_true", help="Skip model validation")
    args = ap.parse_args()

    api_key = require_api_key()

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/venice-video.py (reported line 247)May include surrounding context.

python
ap.add_argument("--out-dir", help="Output directory (default: auto-generated)")
    ap.add_argument("--list-models", action="store_true", help="List available image models and exit")
    ap.add_argument("--list-styles", action="store_true", help="List available style presets and exit")
    ap.add_argument("--no-validate", action="store_true", help="Skip model validation")
    args = ap.parse_args()

    api_key = require_api_key()

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

python
def get_api_key() -> str | None:
    """
    Get API key from multiple sources in order:
    1. VENICE_API_KEY environment variable
    2. ~/.clawdbot/clawdbot.json at skills.entries.venice-ai-media.env.VENICE_API_KEY
    """

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill documents use of environment variables, local files, and outbound network access, but it does not declare an explicit tool scope such as permissions or allowed-tools. That increases the chance the runtime grants broader capabilities than intended and makes review harder because operators cannot quickly verify the minimum required access.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 3)May include surrounding context.

md
---
name: venice-ai-media
description: Generate, edit, and upscale images; create videos from images via Venice AI. Supports text-to-image, image-to-video (Sora, WAN), upscaling, and AI editing.
homepage: https://venice.ai
metadata:
  {

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill recommends storing the Venice API key in a persistent local config file but does not warn about securing that file or limiting access. Persistent plaintext credential storage increases the risk of accidental exposure through backups, shared accounts, permissive file permissions, or local compromise.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 104)May include surrounding context.

Edit an image with AI

python3 {baseDir}/scripts/venice-edit.py photo.jpg --prompt "add sunglasses"

Create a video from an image

python3 {baseDir}/scripts/venice-video.py --image photo.jpg --prompt "gentle camera pan" --duration 5s

text

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill advertises an --embed-exif option that stores prompts in image metadata without warning that prompts may contain sensitive or identifying information. Images are often shared externally, and embedded metadata can persist invisibly, causing unintended disclosure of private prompts, project details, or personal data.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest describes a skill for generating and editing media via Venice AI. While obtaining an API key is expected, this implementation goes beyond direct Venice API interaction by reading a separate local application config file in the user's home directory, which is not an obvious requirement of the stated purpose.

Content

No source excerpt is available for this finding.

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

python
CLAWDBOT_CONFIG_PATH = Path.home() / ".clawdbot" / "clawdbot.json"
USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
API_BASE = "https://api.venice.ai/api/v1"


def get_api_key() -> str | None:

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

python
CLAWDBOT_CONFIG_PATH = Path.home() / ".clawdbot" / "clawdbot.json"
USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
API_BASE = "https://api.venice.ai/api/v1"


def get_api_key() -> str | None:

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

python
CLAWDBOT_CONFIG_PATH = Path.home() / ".clawdbot" / "clawdbot.json"
USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
API_BASE = "https://api.venice.ai/api/v1"


def get_api_key() -> str | None:

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

python
CLAWDBOT_CONFIG_PATH = Path.home() / ".clawdbot" / "clawdbot.json"
USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
API_BASE = "https://api.venice.ai/api/v1"


def get_api_key() -> str | None:

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

python
CLAWDBOT_CONFIG_PATH = Path.home() / ".clawdbot" / "clawdbot.json"
USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
API_BASE = "https://api.venice.ai/api/v1"


def get_api_key() -> str | None:

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

python
CLAWDBOT_CONFIG_PATH = Path.home() / ".clawdbot" / "clawdbot.json"
USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
API_BASE = "https://api.venice.ai/api/v1"


def get_api_key() -> str | None:

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

python
CLAWDBOT_CONFIG_PATH = Path.home() / ".clawdbot" / "clawdbot.json"
USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
API_BASE = "https://api.venice.ai/api/v1"


def get_api_key() -> str | None:

Static analysis

No suspicious patterns detected.