Back to skill

Security audit

Gemini Image

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its image-generation purpose, but its batch workflow can create a recurring task and send images to messaging channels without enough user control.

Review this skill before installing. It is not malicious based on the inspected artifacts, but you should prefer the brew uv installation path, avoid using automatic batch-submit channel delivery unless you explicitly approve the destination and files, treat request JSONL files as trusted input, and run it with a Gemini key and filesystem access limited to the images and output directory you intend to use.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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
Findings (5)

T03 · Remote Payload Retrieval and Execution

Error
Location
README.md:58
Finding
Unverified Remote Installer Executed Through a Shell Pipeline<![CDATA[ ## Vulnerability Details **File Location**: `README.md:58` **Vulnerability Type**: Remote payload retrieval and immediate execution **Risk Level**: High ### Vulnerable Code ```bash 2. [uv](https://docs.astral.sh/uv/) — `brew install uv` or `curl -LsSf https://astral.sh/uv/install.sh | sh` ``` ### Technical Analysis The documented installation command pipes a response downloaded from `https://astral.sh/uv/install.sh` directly into a shell. The retrieved content is not pinned to a particular version and is not inspected or verified through a cryptographic signature or checksum before execution. Although the domain appears to be the official uv installation domain, this construction creates a mutable remote code-execution channel. The effective code executed by users can change after the Skill package has been reviewed. Compromise of the remote hosting account, delivery infrastructure, DNS resolution, or a trusted certificate authority could cause arbitrary commands to be returned and executed. This behavior is not required for image generation. The README already identifies `brew install uv` as an alternative that avoids this direct execution pattern. ### Attack Path 1. A user follows the dependency installation instructions in `README.md`. 2. The shell invokes `curl` and requests the current content of the remote installer. 3. A compromised or malicious delivery source returns modified shell commands. 4. The pipeline passes those commands directly to `sh` without review or integrity verification. 5. The commands execute with all privileges available to the invoking user. ### Impact Assessment A malicious installer could read or modify any data accessible to the current user, including the Gemini API key, OpenClaw configuration, source code, SSH material, and personal files. It could also install persistent processes or modify shell startup files. If the command is run from a privileged shell, impact could extend to system-wide compromise. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Remove the `curl ... | sh` installation alternative from the README. - Prefer a trusted package manager command such as `brew install uv`. - If direct artifact installation must be supported: 1. Pin a specific uv release. 2. Download the installer or binary to a local file rather than piping it to a shell. 3. Verify a publisher-provided cryptographic signature or SHA-256 checksum. 4. Allow the user to inspect the downloaded installer before execution. 5. Execute it without elevated privileges unless elevation is demonstrably necessary. - Document the exact external source, version, and integrity value expected by the Skill. ]]>

T06 · System Persistence

Warning
Location
SKILL.md:109
Finding
Skill Instructions Request a Cross-Session Hourly Scheduled Task<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:109-120` **Vulnerability Type**: Scheduled cross-session persistence **Risk Level**: Medium ### Vulnerable Code ```markdown ### "Batch Submit" Workflow When user says **"batch submit"**, follow this automated workflow: 1. **Submit batch job** — Create JSONL, run `batch.py submit` 2. **Create hourly cron** — Check batch status every hour 3. **On completion** — Download images to specified output directory 4. **Deliver to originating channel** — Send all images to the channel where the request was made (Telegram, Discord, Signal, etc.) 5. **Self-disable cron** — Remove the cron job after successful delivery **Cron job text template:** ``` Check gemini-image batch [BATCH_ID]. If complete: download to [OUTPUT_DIR], send all images to [CHANNEL], then disable this cron job. ``` ``` ### Technical Analysis The Skill directs the hosting agent to create an hourly scheduled task that remains active after the initiating interaction. Asynchronous polling is related to the declared batch-generation feature, but the instructions do not define a maximum lifetime, retry limit, failure cleanup procedure, immutable destination binding, or an auditable mechanism for creating and removing the task. The cron entry is only removed after successful delivery. Failed jobs, download errors, messaging errors, malformed state, revoked credentials, or agent interruption can therefore leave a stale task running indefinitely. The task also performs network requests, file writes, and external-channel delivery across sessions. The Python scripts do not directly install cron entries; the persistence risk arises from the operational instructions given to the agent. ### Attack Path 1. A user or untrusted request invokes the documented “batch submit” workflow. 2. The agent creates an hourly scheduled task containing a batch identifier, output directory, and messaging destination. 3. The scheduled task continues to run indepen ...[truncated 835 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Require explicit user confirmation before creating any scheduled task. - Prefer a platform-provided, narrowly scoped asynchronous job mechanism over unrestricted system cron. - Assign every task a unique immutable identifier associated with one Gemini batch job and one approved destination. - Validate and safely encode the batch ID, output path, and channel identifier before storing them in a task. - Add a maximum lifetime and retry count, such as automatic removal after 24–48 hours or a fixed number of checks. - Remove the task on success, terminal batch failure, authentication failure, malformed state, and repeated delivery failure. - Provide commands for listing and manually deleting every task created by the Skill. - Record creation, execution, and cleanup events in an auditable log without recording the API key. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/batch.py:243
Finding
Batch Result Keys Can Escape the Selected Output Directory<![CDATA[ ## Vulnerability Details **File Location**: `scripts/batch.py:243-262` **Vulnerability Type**: Path traversal and arbitrary file overwrite **Risk Level**: Medium ### Vulnerable Code ```python result = json.loads(line) key = result.get("key", f"image_{saved}") output_path = output_dir / f"{key}.png" if "error" in result: print(f" ✗ {key}: {result['error']}") failed += 1 continue # Find image in response try: response = result.get("response", {}) candidates = response.get("candidates", []) for candidate in candidates: parts = candidate.get("content", {}).get("parts", []) for part in parts: if part.get("inlineData"): img_data = base64.b64decode(part["inlineData"]["data"]) with open(output_path, "wb") as f: f.write(img_data) ``` ### Technical Analysis The `key` field from a downloaded batch result is incorporated directly into a filesystem path. The code does not reject absolute paths, path separators, or `..` traversal components, and it does not verify that the resolved path remains under `output_dir`. For example, a key such as `../../target` produces a path equivalent to `output_dir/../../target.png`. Opening that path with mode `wb` creates or truncates the resulting file. The forced `.png` suffix limits target selection but does not prevent writing outside the intended directory or overwriting an existing user-writable `.png` file. The key originates in the submitted JSONL and is included in the remote batch result. Exploitation therefore requires influence over the request file, returned result, or workflow that constructs request keys. ### Attack Path 1. An attacker supplies or influences a batch request containing a key such as `../../shared/target`. 2. `cmd_submit` accepts the key without validation and submits it as part of the batch request. 3. The Gemini batch result contains that key. 4. The user or scheduled workflow runs `batc ...[truncated 588 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Treat batch keys as identifiers rather than filesystem paths. - Restrict keys to a conservative allowlist, for example letters, digits, underscores, and hyphens. - Reject empty keys, absolute paths, path separators, `.` components, and `..` components. - Resolve the destination and confirm that it remains inside the resolved output directory before writing. - Avoid silently overwriting existing files; use exclusive creation or generate a unique collision-safe filename. - Maintain a separate mapping from arbitrary request keys to locally generated safe filenames. Example hardening pattern: ```python import re key = result.get("key", f"image_{saved}") if not isinstance(key, str) or not re.fullmatch(r"[A-Za-z0-9_-]{1,128}", key): raise ValueError("Unsafe batch result key") base = output_dir.resolve() output_path = (base / f"{key}.png").resolve() if not output_path.is_relative_to(base): raise ValueError("Output path escapes the selected directory") with open(output_path, "xb") as f: f.write(img_data) ``` ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/generate.py:3
Finding
Instant Generation Uses Unpinned Runtime Dependencies<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate.py:3-7` **Vulnerability Type**: Unbounded third-party dependency resolution **Risk Level**: Medium ### Vulnerable Code ```python # /// script # requires-python = ">=3.10" # dependencies = [ # "google-genai>=1.0.0", # "pillow>=10.0.0", # ] # /// ``` ### Technical Analysis The inline dependency metadata specifies minimum versions but no upper bounds, exact versions, lockfile, or package hashes. Running the script through `uv run` can therefore resolve and execute future releases that were not part of the audited Skill package. No evidence shows that the currently named packages are malicious. The risk is that a future compromised package release, compromised publisher account, dependency-chain compromise, or incompatible update could execute during routine Skill use. Python packages can run code during import, and both dependencies are imported before processing images or making API requests. ### Attack Path 1. A user runs `uv run scripts/generate.py`. 2. uv resolves versions satisfying `google-genai>=1.0.0` and `pillow>=10.0.0`. 3. A future compromised or otherwise unsafe compatible release is selected. 4. The package is downloaded and imported by the script. 5. Malicious package code executes with the permissions and environment of the Skill process, potentially including access to `GEMINI_API_KEY`. ### Impact Assessment A compromised dependency could access the Gemini API key, prompts, reference images, generated files, OpenClaw configuration, network resources, and other files available to the current user. It would execute without requiring elevated privileges, but with the full authority of the account running the Skill. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Pin every direct dependency to a reviewed exact version. - Generate and commit a uv lockfile covering direct and transitive dependencies. - Use package hashes or signature verification where supported. - Review dependency updates before changing pinned versions. - Run automated vulnerability and provenance checks against the locked dependency graph. - Execute the script in an isolated environment with access only to required input files, output directories, and the Gemini credential. - Prefer passing the API key through a narrowly scoped secret mechanism rather than exposing broader environment contents. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/batch.py:3
Finding
Batch Generation Uses Unpinned Runtime Dependencies<![CDATA[ ## Vulnerability Details **File Location**: `scripts/batch.py:3-7` **Vulnerability Type**: Unbounded third-party dependency resolution **Risk Level**: Medium ### Vulnerable Code ```python # /// script # requires-python = ">=3.10" # dependencies = [ # "google-genai>=1.0.0", # "pillow>=10.0.0", # ] # /// ``` ### Technical Analysis The batch script permits any future package versions satisfying the specified minimums. There is no lockfile, exact version pin, cryptographic package hash, or upper bound tying execution to dependencies that were reviewed with the Skill. This is particularly sensitive for the batch workflow because the imported Gemini client handles the API credential, uploads prompts and reference images, downloads result files, and accesses locally stored batch state. The Base64 operations in this script are legitimate serialization and deserialization required for inline Gemini image data; they do not themselves constitute covert exfiltration. ### Attack Path 1. A user or scheduled workflow invokes `uv run scripts/batch.py`. 2. uv resolves the latest dependency versions satisfying the broad constraints. 3. A compromised future release or transitive dependency is downloaded. 4. The script imports the package while `GEMINI_API_KEY` is present. 5. Malicious dependency code executes and can access the credential, request files, local images, batch state, and network. ### Impact Assessment A compromised dependency could disclose the Gemini API key, prompts, reference images, uploaded batch content, downloaded results, and batch identifiers. It could also alter local files and make arbitrary network requests within the permissions of the account running the Skill. No privilege escalation beyond that account is inherent in the current code. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Replace minimum-only constraints with exact reviewed versions. - Commit a uv lockfile that pins the full transitive dependency graph. - Verify downloaded artifacts using hashes or trusted package-signing mechanisms. - Perform dependency vulnerability and provenance scanning as part of release review. - Update dependencies only through explicit, reviewed changes. - Run batch processing in a restricted environment with access limited to the required JSONL file, explicitly selected input images, the output directory, and the Gemini API. ]]>
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description says the skill generates or edits images using the Gemini API. However, the supplied code chunk does not perform image generation, editing, style transfer, or reference-image handling. Its actual function is installing the skill locally by creating directories and copying files, plus displaying setup instructions. While installation may support the skill overall, this code chunk’s behavior is materially different from the declared purpose, so this is a mismatch for the supplied code chunk.

Missing User Warnings

High
Confidence
97% confidence
Finding
The documentation instructs automatic delivery of outputs to external channels without any warning or acknowledgment that data will leave the local environment. That is dangerous because generated images, prompts, filenames, and embedded visual content may contain confidential or personal information, and users are not prompted to review or approve the transmission.

External Model or Provider Selection

High
Category
Excessive Agency
Content
Usage:
    uv run generate.py --prompt "description" --output out.png
    uv run generate.py --prompt "combine these" -i ref1.png -i ref2.png --output out.png
    uv run generate.py --prompt "edit this" -i source.png --model gemini-2.5-flash-image --output out.png
"""

import argparse
Confidence
90% confidence
Finding
Skill selects an external model or provider that may use a different account or billing plan than the operator expects. Undisclosed model switches can cause unexpected cost or quota consumption.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill documentation describes capabilities that require environment access, filesystem writes, and network use, but the manifest does not declare any explicit tool scope or permissions boundary. That creates an authorization ambiguity where a host agent may grant broader-than-necessary capabilities, making misuse or unintended side effects harder to constrain or audit.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The manifest presents the skill as image generation/editing, but the markdown instructs autonomous cron-based orchestration and cross-channel delivery to messaging platforms. That materially expands the skill from content generation into task persistence and external data transmission, which changes the trust and threat model and can enable unreviewed exfiltration of generated or user-supplied images.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
Automatically sending generated images to external communication channels is outside the core purpose of an image-generation skill and introduces an unnecessary outbound data path. If prompts, reference images, or outputs contain sensitive information, this behavior could disclose them to third-party platforms or unintended recipients.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The trigger phrase "batch submit" is broad natural-language control for launching a multi-step workflow that includes submission, scheduling, download, and delivery. Without tighter scoping or confirmation, an agent could over-trigger the workflow from ambiguous conversation context and perform actions the user did not intend, including persistent automation and outbound transfer.

Ssd 3

Medium
Confidence
93% confidence
Finding
The workflow creates a natural-language data transmission path from local generation to external messaging channels, which is a common exfiltration pattern. Because the skill also supports user-provided reference images, this could propagate sensitive source material or derived outputs to external services without sufficient review.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- "draft first"

**Edit iterations:**
- **Simple tweaks** (color change, font swap) → Generate directly, no approval needed
- **Structural changes** (new elements, layout changes, removing sections) → Show change summary for approval

## iOS Wireframes
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

External Script Fetching

Low
Category
Supply Chain
Content
## Requirements

1. A Gemini API key (free) — [aistudio.google.com/apikey](https://aistudio.google.com/apikey)
2. [uv](https://docs.astral.sh/uv/) — `brew install uv` or `curl -LsSf https://astral.sh/uv/install.sh | sh`

## Usage
Confidence
91% confidence
Finding
The README recommends piping a remotely fetched shell script directly into `sh`, which executes unverified code from the network immediately. If the hosting site, transport path, or delivered script is compromised, users installing the skill could run attacker-controlled commands on their machine.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
Line L368 includes a language policy statement listing preferred locales and implying a constraint toward those languages. Under the policy, locale restrictions should either offer user choice or be clearly justified as region-specific; this line does neither.