Back to skill

Security audit

Nano Banana Pro OpenRouter

Security checks for vulnerabilities and agentic risk

Overview

This image-generation skill is purpose-aligned but handles API keys unsafely and can send credentials and prompts to an endpoint controlled through local environment files.

Review this skill carefully before installing. It should be changed to avoid agent-readable .env secrets, avoid --api-key command-line passing, stop loading .env from the caller's current directory, restrict OPENROUTER_BASE_URL to the intended OpenRouter endpoint unless explicitly approved, and validate downloaded image URLs. There is no clear evidence of intentional malware, but the current credential and endpoint handling can expose an OpenRouter key and user prompts.

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

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:67
Finding
API Key Exposure Through Agent Context and Command-Line Arguments## Vulnerability Details **File Location**: `SKILL.md:67-70` **Vulnerability Type**: Unnecessary secret access and insecure credential transmission **Risk Level**: High ### Vulnerable Code ```text - If `~/.openclaw/workspace/skills/nano-banana-pro-openrouter/.env` exists: 1. Use the `read` tool to read `.env` 2. Extract `OPENROUTER_API_KEY` and `OPENROUTER_BASE_URL` 3. Always pass the key via `--api-key` when running the script ``` ### Technical Analysis The Skill explicitly instructs the Agent to read a credential file, extract the OpenRouter API key into the Agent's context, and pass that secret as a command-line argument. This access exceeds the minimum privileges needed for image generation. The shell script already loads the Skill-local `.env` file itself, so the Agent does not need to read or process the secret. Passing the key using `--api-key` may additionally expose it through process listings, command logging, execution telemetry, shell history, or tool-call records. ### Attack Path 1. A plaintext API key is stored in the Skill's `.env` file. 2. The Skill instructions direct the Agent to read the entire file. 3. The API key enters the Agent and tool execution context. 4. The Agent invokes the script with `--api-key KEY`. 5. The key may become visible in process arguments, tool logs, execution history, or diagnostic output. 6. A party with access to any of these channels can recover and reuse the credential. ### Impact Assessment Successful exploitation may disclose the OpenRouter API key to other local users, monitoring systems, logs, or parties with access to Agent execution records. A stolen key could be used to consume the victim's API quota, incur charges, or access capabilities associated with the affected OpenRouter account. This does not directly grant operating-system privilege escalation.
Remediation
## Remediation Suggestions - Remove the instructions requiring the Agent to read `.env`. - Do not pass API keys through command-line arguments. - Allow the script to read only its trusted Skill-local `.env`, which it already supports. - Alternatively, supply credentials through a protected file descriptor, standard input, or a dedicated secret manager. - Ensure the credential file has restrictive permissions, such as mode `0600`. - Redact authorization data from all execution logs and error reports.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate_image.sh:139
Finding
Working-Directory Environment Poisoning Can Redirect API Credentials## Vulnerability Details **File Location**: `scripts/generate_image.sh:139-154` **Vulnerability Type**: Untrusted configuration loading and credential exfiltration **Risk Level**: High ### Vulnerable Code ```sh load_env_file "$PWD/.env" load_env_file "$skill_dir/.env" if [ -z "$api_key" ]; then api_key=${OPENROUTER_API_KEY:-} fi if [ -z "$api_key" ]; then echo "Error: No API key provided." >&2 echo "Please either:" >&2 echo " 1. Provide --api-key argument" >&2 echo " 2. Set OPENROUTER_API_KEY environment variable" >&2 exit 1 fi base_url=${OPENROUTER_BASE_URL:-} ``` The loaded variables are subsequently used in the authenticated request: ```sh curl -sS -o "$response_file" -w "%{http_code}" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $api_key" \ -d "$payload" \ "$base_url" ``` ### Technical Analysis The script automatically loads `.env` from the caller's current working directory before loading the Skill-local configuration. The environment loader preserves variables that are already set, so values from `$PWD/.env` take precedence over corresponding values in the Skill-local file. The documentation instructs callers to execute the script using an absolute path without changing into the Skill directory. As a result, the current working directory may be unrelated to the Skill and potentially attacker-controlled. `OPENROUTER_BASE_URL` is accepted without validating its scheme, hostname, or relationship to OpenRouter. An attacker-controlled `.env` can therefore redirect the authenticated request to an arbitrary endpoint. If the API key comes from an existing environment variable, a command-line argument, or another configuration source, the script sends that key and the user's prompt to the attacker-selected server. ### Attack Path 1. An attacker gains write access to the directory from which the user or Agent invokes the Skill. ...[truncated 940 chars]
Remediation
## Remediation Suggestions - Remove automatic loading of `$PWD/.env`. - Load configuration only from a fixed, trusted Skill directory or a user-selected path with verified ownership and restrictive permissions. - Require an HTTPS endpoint. - Allowlist the expected OpenRouter hostname and full API path by default. - Require explicit, informed user authorization before permitting a custom API endpoint. - Reject URLs containing unexpected credentials, ports, fragments, or schemes. - Keep the API key out of command-line arguments and Agent-readable content.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate_image.sh:232
Finding
Unrestricted Fetching of API-Provided URLs Enables Server-Side Request Forgery## Vulnerability Details **File Location**: `scripts/generate_image.sh:232-245` **Vulnerability Type**: Server-side request forgery through unvalidated response URLs **Risk Level**: High ### Vulnerable Code ```sh case "$url" in data:*base64,*) data="${url#*,}" printf '%s' "$data" | base64 -d > "$target_path" ;; data:*) data="${url#*,}" printf '%b' "$(printf '%s' "$data" | sed 's/%/\\x/g')" > "$target_path" ;; *) curl -sS -o "$target_path" "$url" ;; esac ``` ### Technical Analysis Image URLs extracted from the remote API response are passed directly to `curl` without scheme, hostname, port, DNS result, or destination validation. The code assumes that every non-data URL in the response is a safe image location. A malicious or compromised API endpoint can return a URL targeting loopback services, private network systems, link-local addresses, cloud metadata services, or other protocols supported by the installed `curl` build. The response is then written into the Skill's output directory. This risk is amplified by the separately configurable and insufficiently validated `OPENROUTER_BASE_URL`, but exploitation is also possible if the legitimate upstream service or its response path is compromised. ### Attack Path 1. An attacker controls or compromises the configured API endpoint. 2. The endpoint returns a syntactically valid response containing an `image_url` such as a loopback, private-network, or cloud metadata address. 3. The script extracts the attacker-provided URL. 4. The wildcard branch invokes `curl` against that URL. 5. The host running the Skill makes the request from its own network context. 6. The fetched response is stored as a local output file. 7. Depending on access to generated media or output paths, sensitive internal response data may be disclosed. ### Impact Assessment An attacker may cause requests to services reachable from the Skil ...[truncated 371 chars]
Remediation
## Remediation Suggestions - Permit only `https://` image URLs. - Invoke `curl` with a protocol restriction such as `--proto '=https'`. - Allowlist trusted image-delivery hostnames. - Resolve destinations and reject loopback, link-local, private, multicast, unspecified, and reserved address ranges for both IPv4 and IPv6. - Revalidate every redirect destination or disable redirects entirely. - Set conservative connection, transfer, and file-size limits. - Validate the response content type and image signature before publishing the file. - Prefer image data returned directly by the trusted API rather than arbitrary secondary URLs.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_image.sh:164
Finding
Predictable Output Files Can Be Redirected Through Symbolic Links## Vulnerability Details **File Location**: `scripts/generate_image.sh:164-168, 222-244` **Vulnerability Type**: Symbolic-link file overwrite **Risk Level**: Medium ### Vulnerable Code ```sh output_base_dir="$HOME/.openclaw/workspace/outputs/nano-banana-pro-openrouter" mkdir -p "$output_base_dir" output_name=$(basename "$filename") output_path="$output_base_dir/$output_name" ``` ```sh if [ "$index" -eq 1 ]; then target_path="$output_path" else base="${output_path%.*}" ext="${output_path##*.}" if [ "$base" = "$output_path" ]; then target_path="${output_path}-$index" else target_path="${base}-$index.${ext}" fi fi case "$url" in data:*base64,*) data="${url#*,}" printf '%s' "$data" | base64 -d > "$target_path" ;; data:*) data="${url#*,}" printf '%b' "$(printf '%s' "$data" | sed 's/%/\\x/g')" > "$target_path" ;; *) curl -sS -o "$target_path" "$url" ;; esac ``` ### Technical Analysis Applying `basename` prevents direct path traversal through `--filename`, but it does not prevent symbolic-link attacks. The script writes directly to a predictable path and does not reject pre-existing files, verify that the destination is a regular file, or use no-follow and exclusive-creation semantics. If another local process or user can create entries in the output directory, that party can place a symbolic link at the expected output path. Shell redirection and `curl -o` will follow the link and overwrite its target with image or response data. Timestamped automatic filenames reduce predictability but do not eliminate the race condition, particularly when a caller supplies a known filename. ### Attack Path 1. An attacker obtains write access to the output directory or can create a file at the selected output name. 2. The attacker predicts or observes the filename that will be used. 3. The attacker creates a symbolic link from tha ...[truncated 738 chars]
Remediation
## Remediation Suggestions - Ensure the output directory is owned by the Skill user and not writable by other users. - Set a restrictive `umask`, such as `077`, before creating output files. - Reject destinations that already exist, including symbolic links. - Create temporary files atomically with exclusive permissions inside the trusted output directory. - Use no-follow file creation semantics through a suitable helper or safer implementation language. - Validate the destination with `lstat` and atomically rename the completed temporary file into place. - Avoid overwriting an existing filename unless the user explicitly requests replacement and the existing object is verified as a regular file.
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
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Rogue AgentSelf-Modification, Session Persistence
Findings (19)

Credential Access

High
Category
Privilege Escalation
Content
The API base URL must be set via OPENROUTER_BASE_URL. Use the full chat
completions endpoint (for OpenRouter: `https://openrouter.ai/api/v1/chat/completions`).

The script also loads .env files automatically (if present):
- Current working directory .env
- Skill directory .env
Confidence
95% confidence
Finding
By instructing behavior around .env file loading in the working directory and skill directory, the skill encourages credential discovery from local files. In the context of an agent, this is sensitive because .env files often contain unrelated secrets beyond the API key needed for this task.

Credential Access

High
Category
Privilege Escalation
Content
completions endpoint (for OpenRouter: `https://openrouter.ai/api/v1/chat/completions`).

The script also loads .env files automatically (if present):
- Current working directory .env
- Skill directory .env

Important: If a .env file exists, do not ask the user for the key up front.
Confidence
95% confidence
Finding
The documented auto-loading of .env files increases the chance that credentials are sourced from local storage without explicit user awareness. This broadens the attack surface by making secret retrieval part of the normal workflow.

Credential Access

High
Category
Privilege Escalation
Content
The script also loads .env files automatically (if present):
- Current working directory .env
- Skill directory .env

Important: If a .env file exists, do not ask the user for the key up front.
Just run the script and only ask if it errors with "No API key provided."
Confidence
95% confidence
Finding
Telling the agent not to ask the user if a .env file exists reinforces silent credential consumption from local files. In a skill that also sends data to an external API, this materially increases the risk of unauthorized secret use and accidental exposure.

Credential Access

High
Category
Privilege Escalation
Content
- Current working directory .env
- Skill directory .env

Important: If a .env file exists, do not ask the user for the key up front.
Just run the script and only ask if it errors with "No API key provided."

### OpenClaw Chat Execution Rules
Confidence
94% confidence
Finding
This instruction operationalizes secret use without user interaction when a .env file is present. Combined with shell execution and external API calls, it creates an unsafe pattern where the agent is encouraged to discover and use local secrets autonomously.

Credential Access

High
Category
Privilege Escalation
Content
### OpenClaw Chat Execution Rules

- OpenClaw does NOT auto-source the skill .env file
- If `~/.openclaw/workspace/skills/nano-banana-pro-openrouter/.env` exists:
  1. Use the `read` tool to read `.env`
  2. Extract `OPENROUTER_API_KEY` and `OPENROUTER_BASE_URL`
Confidence
99% confidence
Finding
The skill specifically directs the agent to read a concrete .env path under the workspace. This is a direct credential-access pattern and is especially risky because it turns secret file inspection into an expected execution step rather than an exceptional admin task.

Ssd 3

High
Confidence
99% confidence
Finding
The skill explicitly instructs the agent to read secrets from a .env file, extract the API key, and pass it on the command line. This is dangerous because it causes direct secret handling by the agent and may expose credentials through logs, process listings, transcripts, or downstream tooling.

Credential Access

High
Category
Privilege Escalation
Content
1. Use the `read` tool to read `.env`
  2. Extract `OPENROUTER_API_KEY` and `OPENROUTER_BASE_URL`
  3. Always pass the key via `--api-key` when running the script
- Only ask the user if .env is missing or the key cannot be read
- If the user asks for a timestamped filename, prefer `--filename auto` (do not handwrite dates)

If neither is available, the script exits with an error message.
Confidence
99% confidence
Finding
The agent is told to always pass the extracted API key via --api-key after reading .env. Passing secrets on the command line can expose them through process arguments, audit logs, shell history, or telemetry, compounding the credential-access risk.

Credential Access

High
Category
Privilege Escalation
Content
- `command -v base64` (must exist)

Common failures:
- `Error: No API key provided.` -> read .env and retry with --api-key; if still failing, ask the user to set OPENROUTER_API_KEY
- `Error: No API base URL provided.` -> ensure OPENROUTER_BASE_URL is set to a full chat completions endpoint
- `Error loading input image:` -> wrong path or unreadable file; verify --input-image points to a real image
- "quota/permission/403" style API errors -> wrong key, no access, or quota exceeded; try a different key/account
Confidence
98% confidence
Finding
The troubleshooting guidance explicitly tells the agent to read .env and retry with --api-key on failure. This bakes credential retrieval and insecure secret transmission into error handling, making the unsafe path more likely during normal use.

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-image.png`

Tip: To avoid incorrect timestamps, pass `--filename auto` and let the script
generate the filename using the system clock.
Confidence
80% confidence
Finding
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Credential Access

High
Category
Privilege Escalation
Content
script_dir=$(cd "$(dirname "$0")" && pwd)
skill_dir=$(cd "$script_dir/.." && pwd)

load_env_file "$PWD/.env"
load_env_file "$skill_dir/.env"

if [ -z "$api_key" ]; then
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
script_dir=$(cd "$(dirname "$0")" && pwd)
skill_dir=$(cd "$script_dir/.." && pwd)

load_env_file "$PWD/.env"
load_env_file "$skill_dir/.env"

if [ -z "$api_key" ]; then
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill invokes shell commands but does not declare a restrictive tool scope such as allowed-tools or permissions. That increases the chance the agent can use shell more broadly than intended, which weakens sandboxing and review controls for a networked, file-accessing skill.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The invocation criteria are broad enough to trigger on generic image-generation requests, which can cause the agent to route more conversations than necessary into a shell-based external API workflow. Over-broad activation increases unnecessary exposure of prompts, files, and credentials to this skill's execution path.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
At L018 the file says the shell version supports generation only and no input image editing. However, later lines reference '--input-image' failures and discuss image editing support, which actively conflicts with the earlier limitation and could cause the agent to attempt unsupported behavior.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill does not clearly disclose that user prompts and related metadata will be sent to OpenRouter, a third-party external service. This undermines informed consent and can lead to unintended disclosure of sensitive or proprietary user content.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The documentation tells the agent to read local .env files and extract credentials, which expands the skill from image generation into secret discovery and handling. Even if intended for convenience, instructing an agent to inspect local secret stores creates an unnecessary credential exposure path and normalizes secret harvesting behavior.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- Current working directory .env
- Skill directory .env

Important: If a .env file exists, do not ask the user for the key up front.
Just run the script and only ask if it errors with "No API key provided."

### OpenClaw Chat Execution Rules
Confidence
80% 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.

Session Persistence

Medium
Category
Rogue Agent
Content
2. Extract `OPENROUTER_API_KEY` and `OPENROUTER_BASE_URL`
  3. Always pass the key via `--api-key` when running the script
- Only ask the user if .env is missing or the key cannot be read
- If the user asks for a timestamped filename, prefer `--filename auto` (do not handwrite dates)

If neither is available, the script exits with an error message.
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.

External Transmission

Medium
Category
Data Exfiltration
Content
response_file=$(mktemp)
trap 'rm -f "$response_file"' EXIT

if ! http_code=$(curl -sS -o "$response_file" -w "%{http_code}" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $api_key" \
  -d "$payload" \
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.