Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

Nano Banana 2 — Gemini Image Generation

v0.1.0

Gemini image generation, editing, and search-grounded image creation via gemini-3.1-flash-image-preview (Nano Banana 2). USE FOR: - Generating images from te...

0· 550·1 current·1 all-time
Security Scan
VirusTotalVirusTotal
Suspicious
View report →
OpenClawOpenClaw
Suspicious
high confidence
Purpose & Capability
The SKILL.md implements exactly what the description claims (text->image, image edit, and search-grounded generation using gemini-3.1-flash-image-preview). However, the registry metadata listed no required environment variables or primary credential while the SKILL.md clearly requires GEMINI_API_KEY. That metadata omission is an incoherence that should be corrected or explained.
Instruction Scope
The runtime instructions are narrowly scoped to making API calls to the Google generativelanguage endpoint, saving image files to .nano-banana/, and handling responses. The instructions do not ask the agent to read unrelated files or contact unexpected endpoints. They do instruct the user/agent to set and verify GEMINI_API_KEY and to write outputs to local files (and to add them to .gitignore).
Install Mechanism
This is an instruction-only skill with no install spec and no code files to write to disk; that minimizes install-time risk. Allowed-tools list includes bash and python, which matches the provided examples.
!
Credentials
The SKILL.md requires a GEMINI_API_KEY credential (used in an x-goog-api-key header) which is expected for this purpose. The concern is that the registry metadata did not declare this requirement, so the skill's manifest does not accurately advertise the secret it needs. The setup instructions also recommend persisting the key in shell rc or a project .env file — which is user-facing guidance that could lead to accidental key leakage if not handled carefully.
Persistence & Privilege
The skill does not request always:true, does not modify other skills or system configuration, and is user-invocable only. It does recommend writing the API key into user shell/profile or a .env file if the user chooses, but that is a user action rather than an autonomous modification performed by the skill itself.
What to consider before installing
This skill appears to be what it says (a Gemini image-generation helper) and uses the Google generativelanguage API. Before installing or using it: (1) confirm the registry metadata is updated to declare GEMINI_API_KEY so you know what credentials the skill needs; (2) do not hardcode the key into files you will commit — prefer an ephemeral session env or a secrets manager; if you must use ~/.zshrc or a .env file, add the file to .gitignore and understand the persistence risk; (3) verify the skill's owner/source (source/homepage are unknown here) — if you don't trust the publisher, don't supply high-privilege keys; (4) review billing/quota on your Google AI Studio project because image generation can incur charges. If you want a lower-risk approach, run the provided example code manually in an isolated environment rather than enabling any automatic invocation.

Like a lobster shell, security has layers — review code before you run it.

geminivk97aeyn0dsbshd8bba577f25j18227vrgenerative-aivk97aeyn0dsbshd8bba577f25j18227vrimagevk97aeyn0dsbshd8bba577f25j18227vrlatestvk97aeyn0dsbshd8bba577f25j18227vr
550downloads
0stars
1versions
Updated 7h ago
v0.1.0
MIT-0

nano-banana-2

Gemini image generation and editing via gemini-3.1-flash-image-preview. All output images are written to .nano-banana/ in the current project directory.

Prerequisites

GEMINI_API_KEY must be set in the environment. Verify with:

echo $GEMINI_API_KEY

If empty, see rules/setup.md. For output handling and security guidelines, see rules/security.md.

Workflow

Follow this escalation pattern:

  1. Generate - Create a new image from a text prompt only.
  2. Edit - Modify an existing local image with a text instruction.
  3. Search-Grounded - Generate informed by live web/image search results (use when current visual references, styles, or real-world accuracy matter).
GoalOperationWhen
Create image from scratchgenerateNo source image; prompt is self-contained
Modify or extend an existing imageeditHave a local PNG/JPEG to transform
Ground output in current web datasearch-groundedNeed up-to-date styles or real-world references

Output & Organization

All images are saved to .nano-banana/ in the current working directory. Add .nano-banana/ to .gitignore to prevent generated assets from being committed.

mkdir -p .nano-banana
echo ".nano-banana/" >> .gitignore

Naming conventions:

.nano-banana/gen-{slug}-{timestamp}.png
.nano-banana/edit-{slug}-{timestamp}.png
.nano-banana/search-{slug}-{timestamp}.png

Where {slug} is a short kebab-case label from the first 4-5 words of the prompt, and {timestamp} is YYYYMMDD-HHMMSS.

After saving, open to confirm the result:

open "$(ls -t .nano-banana/*.png | head -1)"

API Reference

PropertyValue
Modelgemini-3.1-flash-image-preview
Endpointhttps://generativelanguage.googleapis.com/v1beta/models/gemini-3.1-flash-image-preview:generateContent
Auth headerx-goog-api-key: $GEMINI_API_KEY
Image outputcandidates[0].content.parts[].inlineData.data (base64 PNG)

Resolution options (imageConfig.imageSize)

ValueResolution
5120.5K (fastest)
10241K (default)
20482K
40964K

Aspect ratio options (imageConfig.aspectRatio)

1:1, 16:9, 9:16, 1:4, 4:1, 1:8, 8:1, 2:3, 3:2

Thinking mode (generationConfig.thinkingConfig.thinkingBudget)

An integer token budget. Set inside generationConfig, not at the top level.

ValueBehaviour
0Thinking off — fastest, lowest cost (default)
1024Light thinking
8192Deep thinking — recommended for grounded tasks

Operations

1. Generate (text-to-image)

python3 - <<'PYEOF'
import os, base64, json, urllib.request, datetime

api_key = os.environ["GEMINI_API_KEY"]
prompt  = "a majestic mountain at sunrise, photorealistic"
slug    = "mountain-sunrise"
size    = "1024"    # 512 | 1024 | 2048 | 4096
aspect  = "16:9"   # 1:1 | 16:9 | 9:16 | 1:4 | 4:1 | 1:8 | 8:1 | 2:3 | 3:2
thinking = 0       # 0 = off, 1024 = light, 8192 = deep

payload = {
    "contents": [{"parts": [{"text": prompt}]}],
    "generationConfig": {
        "responseModalities": ["TEXT", "IMAGE"],
        "imageConfig": {"imageSize": size, "aspectRatio": aspect},
        "thinkingConfig": {"thinkingBudget": thinking}
    }
}

url = (
    "https://generativelanguage.googleapis.com/v1beta/models/"
    "gemini-3.1-flash-image-preview:generateContent"
)
req = urllib.request.Request(
    url,
    data=json.dumps(payload).encode(),
    headers={"Content-Type": "application/json", "x-goog-api-key": api_key},
    method="POST"
)
with urllib.request.urlopen(req) as resp:
    data = json.load(resp)

ts  = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
out = f".nano-banana/gen-{slug}-{ts}.png"
os.makedirs(".nano-banana", exist_ok=True)

for part in data["candidates"][0]["content"]["parts"]:
    if part.get("inlineData", {}).get("mimeType", "").startswith("image/"):
        with open(out, "wb") as f:
            f.write(base64.b64decode(part["inlineData"]["data"]))
        print(f"Saved: {out}")
        break
    elif part.get("text"):
        print("Model:", part["text"])
PYEOF

2. Edit (image-to-image)

The source image is base64-encoded and sent alongside the instruction text. Supports PNG and JPEG inputs.

python3 - <<'PYEOF'
import os, base64, json, urllib.request, datetime

api_key     = os.environ["GEMINI_API_KEY"]
source_img  = "path/to/source.png"          # change to actual path
instruction = "Make the sky purple and add stars"
slug        = "purple-sky-stars"
size        = "1024"
aspect      = "1:1"
thinking    = 0   # 0 = off, 1024 = light, 8192 = deep

with open(source_img, "rb") as f:
    img_b64 = base64.b64encode(f.read()).decode()

ext  = source_img.rsplit(".", 1)[-1].lower()
mime = "image/jpeg" if ext in ("jpg", "jpeg") else "image/png"

payload = {
    "contents": [{
        "parts": [
            {"text": instruction},
            {"inline_data": {"mime_type": mime, "data": img_b64}}
        ]
    }],
    "generationConfig": {
        "responseModalities": ["TEXT", "IMAGE"],
        "imageConfig": {"imageSize": size, "aspectRatio": aspect},
        "thinkingConfig": {"thinkingBudget": thinking}
    }
}

url = (
    "https://generativelanguage.googleapis.com/v1beta/models/"
    "gemini-3.1-flash-image-preview:generateContent"
)
req = urllib.request.Request(
    url,
    data=json.dumps(payload).encode(),
    headers={"Content-Type": "application/json", "x-goog-api-key": api_key},
    method="POST"
)
with urllib.request.urlopen(req) as resp:
    data = json.load(resp)

ts  = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
out = f".nano-banana/edit-{slug}-{ts}.png"
os.makedirs(".nano-banana", exist_ok=True)

for part in data["candidates"][0]["content"]["parts"]:
    if part.get("inlineData", {}).get("mimeType", "").startswith("image/"):
        with open(out, "wb") as f:
            f.write(base64.b64decode(part["inlineData"]["data"]))
        print(f"Saved: {out}")
        break
    elif part.get("text"):
        print("Model:", part["text"])
PYEOF

3. Search-Grounded Generation

Adds googleSearch with both webSearch and imageSearch types to ground the output in live web data. Use when the prompt references real-world subjects, current styles, recent events, or factual visual accuracy.

python3 - <<'PYEOF'
import os, base64, json, urllib.request, datetime

api_key  = os.environ["GEMINI_API_KEY"]
prompt   = "Generate a product photo of the latest iPhone model"
slug     = "latest-iphone-product"
size     = "1024"
aspect   = "1:1"
thinking = 8192   # deeper thinking recommended for grounded generation

payload = {
    "contents": [{"parts": [{"text": prompt}]}],
    "tools": [{
        "googleSearch": {
            "searchTypes": ["webSearch", "imageSearch"]
        }
    }],
    "generationConfig": {
        "responseModalities": ["TEXT", "IMAGE"],
        "imageConfig": {"imageSize": size, "aspectRatio": aspect},
        "thinkingConfig": {"thinkingBudget": thinking}
    }
}

url = (
    "https://generativelanguage.googleapis.com/v1beta/models/"
    "gemini-3.1-flash-image-preview:generateContent"
)
req = urllib.request.Request(
    url,
    data=json.dumps(payload).encode(),
    headers={"Content-Type": "application/json", "x-goog-api-key": api_key},
    method="POST"
)
with urllib.request.urlopen(req) as resp:
    data = json.load(resp)

ts  = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
out = f".nano-banana/search-{slug}-{ts}.png"
os.makedirs(".nano-banana", exist_ok=True)

for part in data["candidates"][0]["content"]["parts"]:
    if part.get("inlineData", {}).get("mimeType", "").startswith("image/"):
        with open(out, "wb") as f:
            f.write(base64.b64decode(part["inlineData"]["data"]))
        print(f"Saved: {out}")
        break
    elif part.get("text"):
        print("Model:", part["text"])
PYEOF

Working with Results

# List all generated images
ls -lh .nano-banana/

# Open the most recent
open "$(ls -t .nano-banana/*.png | head -1)"

# Open all images generated today
open .nano-banana/*$(date +%Y%m%d)*.png

Error Handling

If the API returns an error, the response will contain an error key. Print it with:

python3 -c "
import json, sys
d = json.loads(sys.stdin.read())
if 'error' in d:
    print('API Error:', json.dumps(d['error'], indent=2))
elif not d.get('candidates'):
    print('No candidates:', json.dumps(d, indent=2))
"

Common errors:

Error codeCause
API_KEY_INVALIDGEMINI_API_KEY not set or incorrect
RESOURCE_EXHAUSTEDQuota exceeded; check billing or wait
INVALID_ARGUMENTBad imageSize or aspectRatio value
Empty candidatesSafety filter blocked the prompt or source image
404 Not FoundModel not yet available on your API key; see setup

Comments

Loading comments...