This is a client library issue. The live_music.py module transmits the API key redundantly in the WebSocket URL query string, inconsistent with how live.py handles the same authentication in the same SDK.
Environment details
- Programming language: Python
- OS: All (platform-independent code path)
- Language runtime version: Python 3.9+
- Package version: Current main branch (affects all versions with
live_music.py)
Steps to reproduce
- Initialize a client with an API key:
from google import genai
client = genai.Client(api_key="YOUR_API_KEY")
- Connect to the live music WebSocket:
async with client.aio.live.music.connect(
model="models/lyria-realtime-exp"
) as session:
pass
- Observe the WebSocket connection URL constructed at
live_music.py line 180:
wss://generativelanguage.googleapis.com/ws/google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateMusic?key=YOUR_API_KEY
- Note that
self._api_client._http_options.headers (line 182) already contains:
x-goog-api-key: YOUR_API_KEY
This header is passed via additional_headers to the WebSocket connection.
The API key is therefore transmitted twice:
- Once in the URL query string (visible in logs, tracebacks, monitoring systems)
- Once in the request header (the secure/preferred method)
Comparison with live.py
live.py line 981 constructs the URI without the query parameter:
uri = f'{base_url}/ws/google.ai.generativelanguage.{version}.GenerativeService.{method}'
Authentication relies solely on the x-goog-api-key header passed via additional_headers.
This matches Google Cloud API key best practices:
"Avoid using query parameters to provide your API key to Google APIs. Use the x-goog-api-key HTTP header or a client library instead."
Impact
The URL-embedded API key may be exposed to:
- Corporate proxy logs (HTTPS-terminating proxies log full URLs)
- Python tracebacks on connection failure
- Application logging / APM systems capturing connection URLs
- Network monitoring tooling
Suggested fix
# live_music.py line 180 — remove ?key={api_key} from URI
# Before:
uri = f'{base_url}/ws/google.ai.generativelanguage.{version}.GenerativeService.BidiGenerateMusic?key={api_key}'
# After:
uri = f'{base_url}/ws/google.ai.generativelanguage.{version}.GenerativeService.BidiGenerateMusic'
The header already provides authentication.
If the server requires the query parameter for this specific endpoint, then the redundant header should be removed instead — but either way, sending the API key in both locations is unnecessary.
This is a client library issue. The
live_music.pymodule transmits the API key redundantly in the WebSocket URL query string, inconsistent with howlive.pyhandles the same authentication in the same SDK.Environment details
live_music.py)Steps to reproduce
live_music.pyline 180:self._api_client._http_options.headers(line 182) already contains:This header is passed via
additional_headersto the WebSocket connection.The API key is therefore transmitted twice:
Comparison with
live.pylive.pyline 981 constructs the URI without the query parameter:Authentication relies solely on the
x-goog-api-keyheader passed viaadditional_headers.This matches Google Cloud API key best practices:
Impact
The URL-embedded API key may be exposed to:
Suggested fix
The header already provides authentication.
If the server requires the query parameter for this specific endpoint, then the redundant header should be removed instead — but either way, sending the API key in both locations is unnecessary.