Back to skill

Security audit

Nano Banana Pro via cheaper grsai.com

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it claims, but it sends prompts/images to a third-party API and unsafely downloads whatever result URL that service returns.

Review before installing. Use it only if you are comfortable sending prompts and any edited images to the grsai API, prefer a protected GRSAI_API_KEY over chat or command-line keys, and avoid running it in environments with sensitive internal network access unless URL validation and download limits are added.

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

Warning
Location
scripts/generate_image.py:250
Finding
Unvalidated Provider-Controlled URL Enables SSRF and Arbitrary Resource Retrieval## Vulnerability Details **File Location**: `scripts/generate_image.py`, lines 250–259 **Vulnerability Type**: Server-Side Request Forgery (SSRF) and unrestricted URL scheme handling **Risk Level**: Medium **Vulnerable Code**: ```python image_url = result["results"][0]["url"] content = result["results"][0].get("content", "") if content: print(f"Model response: {content}") print("Downloading image...") try: with urllib.request.urlopen(image_url, timeout=60 * 2) as resp: output_path.write_bytes(resp.read()) except Exception as e: ``` ### Technical Analysis The image URL returned by the remote generation provider is passed directly to `urllib.request.urlopen()` without validation. The code does not restrict the URL scheme, allowlist trusted CDN hostnames, reject private or reserved IP addresses, validate redirect destinations, limit response size, or verify that the response is an image. Because `urlopen()` supports multiple URL schemes and automatically follows HTTP redirects, a compromised or malicious API response could direct the process to: - Loopback services such as `127.0.0.1`. - Private network services accessible from the host. - Link-local cloud metadata endpoints. - Unexpected local or remote resources supported by the URL handler. - An initially trusted URL that redirects to a prohibited destination. The provider-controlled response body is then written to the user-selected output path without content validation. Although the retrieved content is not subsequently transmitted elsewhere by this script, the behavior creates an SSRF primitive and may expose local or internal content in the output file. ### Attack Path 1. A user invokes the Skill to generate or edit an image. 2. The script submits the prompt and optional input image to `grsaiapi.com`. 3. The provider account, API infrastructure, or returned task data is compromised or manipulated. 4. The task result supplies ...[truncated 1058 chars]
Remediation
## Remediation Suggestions - Accept only `https` result URLs. - Maintain an explicit allowlist of expected image CDN hostnames. - Resolve the destination hostname and reject loopback, private, link-local, multicast, unspecified, and reserved addresses for both IPv4 and IPv6. - Disable automatic redirects or validate the scheme, hostname, port, and resolved addresses of every redirect destination. - Enforce a maximum response size using both `Content-Length` and bounded streaming reads. - Require an expected image `Content-Type`. - Decode and validate the downloaded file as a supported image before committing it to the final output path. - Download to a securely created temporary file and atomically rename it after successful validation. - Consider having the trusted API return image bytes through an authenticated endpoint rather than accepting arbitrary result URLs.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/generate_image.py:153
Finding
API Key Exposure Through Command-Line Arguments## Vulnerability Details **File Location**: `scripts/generate_image.py`, line 153 **Vulnerability Type**: Sensitive credential exposure through process arguments **Risk Level**: Low **Vulnerable Code**: ```python parser.add_argument("--api-key", "-k", help="grsai API key (overrides GRSAI_API_KEY env var)") ``` The accompanying `SKILL.md` documentation also recommends the following invocation pattern: ```bash uv run ~/.codex/skills/nano-banana-pro/scripts/generate_image.py \ --prompt "your image description" \ --filename "output-name.png" \ --api-key KEY ``` ### Technical Analysis Supplying credentials through command-line arguments can expose them through shell history, process listings, execution telemetry, audit logs, terminal recordings, and wrapper-tool diagnostics. The documentation also permits using a key supplied in chat, which unnecessarily places the credential in conversation records before it reaches the command line. Supporting the `GRSAI_API_KEY` environment variable is safer than exposing the key as an argument, although protected credential injection or a secret manager would provide stronger isolation. ### Attack Path 1. A user follows the documented workflow and includes the API key in the `--api-key` argument. 2. The complete command is retained in shell history, Agent execution logs, or terminal telemetry, or is visible in the process argument list while the program runs. 3. Another local user, process-monitoring component, log reader, or person with access to conversation history obtains the credential. 4. The exposed key is used to make unauthorized requests to the image-generation service until the key is revoked or expires. ### Impact Assessment Exposure grants the attacker the API permissions associated with the compromised key. This may permit unauthorized image-generation requests, account quota consumption, billing impact, and access to any provider-side operations author ...[truncated 233 chars]
Remediation
## Remediation Suggestions - Remove the `--api-key` option or mark it as deprecated and unsafe. - Prefer a protected credential store, runtime secret injection, or the existing `GRSAI_API_KEY` environment variable. - If interactive use is required, obtain the key through a hidden prompt such as `getpass.getpass()` rather than command-line arguments. - Update `SKILL.md` so it does not instruct users to provide secrets in chat or place them directly on the command line. - Ensure application logs never print authorization headers or credential values. - Recommend immediate rotation if a key has already been shared through chat, logs, or shell history.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (5)

Memory Manipulation

High
Category
Memory Poisoning
Content
- Prompt "A serene Japanese garden" → `2025-11-23-14-23-05-japanese-garden.png`
- Prompt "sunset over mountains" → `2025-11-23-15-30-12-sunset-mountains.png`
- Prompt "create an image of a robot" → `2025-11-23-16-45-33-robot.png`
- Unclear context → `2025-11-23-17-12-48-x9k2.png`

## Image Editing
Confidence
80% confidence
Finding
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill instructs use of a script that accesses environment variables, reads and writes files, and makes network requests, but the manifest does not declare any tool scope or permissions. That creates a transparency and policy-enforcement gap: users and hosting systems cannot clearly assess or constrain what the skill is allowed to do before execution.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The skill sends user prompts and, for edits, local input images to the external grsai.com API, but the description and usage text do not prominently warn the user about this data transfer. This can lead to unintentional disclosure of sensitive text, proprietary images, or personal data to a third-party service.

Indirect Prompt Extraction

Medium
Category
System Prompt Leakage
Content
- `Error: No API key provided.` → set `GRSAI_API_KEY` or pass `--api-key`
  - `Error loading input image:` → wrong path / unreadable file
  - HTTP 401 → wrong or expired API key
  - `Generation failed:` → content moderation or invalid input; rephrase prompt

## Filename Generation
Confidence
75% confidence
Finding
Skill contains patterns that could indirectly extract system prompts through rephrasing, translation, summarization, or side-channel techniques.

Session Persistence

Medium
Category
Rogue Agent
Content
Examples:
- Prompt "A serene Japanese garden" → `2025-11-23-14-23-05-japanese-garden.png`
- Prompt "sunset over mountains" → `2025-11-23-15-30-12-sunset-mountains.png`
- Prompt "create an image of a robot" → `2025-11-23-16-45-33-robot.png`
- Unclear context → `2025-11-23-17-12-48-x9k2.png`

## Image Editing
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.