T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/nano_banana_api.py:81
- Finding
- Arbitrary API Base URL Override Can Disclose Credentials and User Data## Vulnerability Details **File Location**: `scripts/nano_banana_api.py`, lines 81–85 and 216–223 **Vulnerability Type**: Unvalidated network destination for authenticated requests **Risk Level**: Medium The CLI supports the undocumented `NANO_BANANA_BASE_URL` environment variable. This variable controls the destination of API requests without validating the URL scheme or hostname. The application subsequently attaches the Nano Banana Bearer token to requests sent to that destination. ### Vulnerable Code General JSON requests at lines 81–85: ```python base_url = os.getenv("NANO_BANANA_BASE_URL", DEFAULT_BASE_URL).rstrip("/") url = f"{base_url}{path}" headers = build_headers(api_key, require_auth=require_auth, include_json=body is not None) payload = None if body is None else json.dumps(body).encode("utf-8") request = urllib.request.Request(url, data=payload, headers=headers, method=method) ``` Streaming generation requests at lines 216–223: ```python base_url = os.getenv("NANO_BANANA_BASE_URL", DEFAULT_BASE_URL).rstrip("/") headers = build_headers(args.api_key, require_auth=True, include_json=True) request = urllib.request.Request( f"{base_url}/generate", data=json.dumps(body).encode("utf-8"), headers=headers, method="POST", ) ``` The associated header construction adds the credential to any configured destination: ```python resolved_key = get_api_key(api_key) if resolved_key: headers["Authorization"] = f"Bearer {resolved_key}" ``` ### Technical Analysis Sending the API key and generation data to the documented endpoint, `https://www.nananobanana.com/api/v1`, is necessary for the Skill's declared image-generation functionality. However, allowing an environment variable to silently replace that endpoint exceeds the minimum privilege needed for normal operation. No validation ensures that the override: - Uses HTTPS. - Resolves to the official Nano Banana hostname ...[truncated 2155 chars]
- Remediation
- ## Remediation Suggestions 1. Remove `NANO_BANANA_BASE_URL` if custom endpoints are not required. Always use the documented constant: ```python base_url = DEFAULT_BASE_URL ``` 2. If an override is required for development, enforce HTTPS and validate the hostname before adding credentials: ```python parsed = urllib.parse.urlparse(base_url) if parsed.scheme != "https": raise SystemExit("The API base URL must use HTTPS.") if parsed.hostname != "www.nananobanana.com": raise SystemExit("Refusing to send credentials to an untrusted API host.") ``` 3. Separate endpoint customization from credential forwarding. Never attach the production API key to a non-official hostname by default. 4. Require an explicit command-line option and informed confirmation for custom endpoints rather than silently trusting an inherited environment variable. 5. Apply the same centralized URL-validation function to both `request_json()` and `handle_stream()` so streaming requests cannot bypass the control. 6. Reject URLs containing embedded credentials, unexpected ports, fragments, or non-HTTP(S) schemes. Normalize and compare parsed hostnames rather than using substring or suffix checks. 7. Document all supported endpoint overrides and warn users that prompts, reference-image URLs, generation IDs, and credentials are transmitted to the selected service. 8. Prefer environment variables over the `--api-key` argument for credentials because command-line arguments may be visible in process listings or shell history.
