C2 --dry-run checks, 2026-10-30 08:52-08:53 (UTC+8). Each run: unshare -rn (no network namespace) + HTTPS_PROXY/HTTP_PROXY pointed at a logging listener on 127.0.0.1:8899 inside it (04a-netwatch.sh.txt), env -i, empty HOME, GEMINI_API_KEY=FAKE-KEY-<16 random hex> (fresh per batch, not a real key), DBUS_SESSION_BUS_ADDRESS pointed at our own listening unix socket that logs every connect (keychain detector). == generate: rc=0, proxy hits=0 {"dry_run":true,"request":{"method":"POST","url":"https://generativelanguage.googleapis.com/v1beta/interactions","headers":{"Accept":["text/event-stream"],"Content-Type":["application/json"],"User-Agent":["google-genai-cli/0.4.4 gl-go/go1.26.10"],"X-Goog-Api-Key":["[REDACTED]"]},"body":{"input":"Hello from my agent","model":"gemini-3.8-flash","stream":true}}} == image: rc=0, proxy hits=0 {"dry_run":true,"request":{"method":"POST","url":"https://generativelanguage.googleapis.com/v1beta/interactions","headers":{"Accept":["application/json;q=1, text/event-stream;q=0"],"Content-Type":["application/json"],"User-Agent":["google-genai-cli/0.4.4 gl-go/go1.26.10"],"X-Goog-Api-Key":["[REDACTED]"]},"body":{"input":"A friendly robot mascot in a sunlit workshop, composed on the right with uncluttered space on the left for a landing page headline. No text or watermark.","model":"gemini-nano-banana-2.1","response_format":{"aspect_ratio":"16:9","image_size":"2K","type":"image"},"store":false,"stream":false}}} == tts: rc=0, proxy hits=0 {"dry_run":true,"request":{"method":"POST","url":"https://generativelanguage.googleapis.com/v1beta/interactions","headers":{"Accept":["application/json;q=1, text/event-stream;q=0"],"Content-Type":["application/json"],"User-Agent":["google-genai-cli/0.4.4 gl-go/go1.26.10"],"X-Goog-Api-Key":["[REDACTED]"]},"body":{"generation_config":{"speech_config":[{"voice":"Kore"}]},"input":[{"text":"Hello from the TTS test.","type":"text"}],"model":"gemini-3.8-flash-tts","response_format":{"type":"audio"},"store":false,"stream":false}}} == analyze: rc=0, proxy hits=0 {"dry_run":true,"request":{"method":"POST","url":"https://generativelanguage.googleapis.com/v1beta/interactions","headers":{"Accept":["application/json;q=1, text/event-stream;q=0"],"Content-Type":["application/json"],"User-Agent":["google-genai-cli/0.4.4 gl-go/go1.26.10"],"X-Goog-Api-Key":["[REDACTED]"]},"body":{"input":[{"data":"","mime_type":"application/pdf","type":"document"},{"text":"When does Project Kestrel launch?","type":"text"}],"model":"gemini-3.8-flash","store":false,"stream":false}}} == agent: rc=0, proxy hits=0 {"dry_run":true,"request":{"method":"POST","url":"https://generativelanguage.googleapis.com/v1beta/interactions","headers":{"Accept":["text/event-stream"],"Content-Type":["application/json"],"User-Agent":["google-genai-cli/0.4.4 gl-go/go1.26.10"],"X-Goog-Api-Key":["[REDACTED]"]},"body":{"agent":"deep-research-preview-04-2026","background":true,"input":"Research battery recycling approaches and cite sources","stream":true}}} == models: rc=0, proxy hits=0 {"dry_run":true,"request":{"method":"GET","url":"https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000","headers":{"Accept":["application/json"],"User-Agent":["google-genai-cli/0.4.4 gl-go/go1.26.10"],"X-Goog-Api-Key":["[REDACTED]"]},"body":null}} == bad-size: rc=0, proxy hits=0 {"dry_run":true,"request":{"method":"POST","url":"https://generativelanguage.googleapis.com/v1beta/interactions","headers":{"Accept":["application/json;q=1, text/event-stream;q=0"],"Content-Type":["application/json"],"User-Agent":["google-genai-cli/0.4.4 gl-go/go1.26.10"],"X-Goog-Api-Key":["[REDACTED]"]},"body":{"input":"x","model":"gemini-nano-banana-2.1","response_format":{"image_size":"3K","type":"image"},"stream":false}}} == bad-json: rc=2, proxy hits=0 { "error": "failed to parse --body as JSON: unexpected end of JSON input", "error_reason": "CLI_VALIDATION", "error_type": "validation_error", "exit_code": 2, "hints": [ "Run the command with --help for runnable examples, or --usage for the machine-readable surface" ], "message": "failed to parse --body as JSON: unexpected end of JSON input" } == missing-file: rc=2, proxy hits=0 { "error": "--input[1] \"does-not-exist.pdf\": file not found; for an uploaded file pass files/\u003cid\u003e", "error_reason": "CLI_VALIDATION", "error_type": "validation_error", "exit_code": 2, "hints": [ "Run the command with --help for runnable examples, or --usage for the machine-readable surface" ], "message": "--input[1] \"does-not-exist.pdf\": file not found; for an uploa Commands: generate 'Hello from my agent' | image --body @03b-readme-hero-image.json --out ./assets/hero.jpg | tts '...' --out ./assets/t.wav | analyze -i brief.pdf (14,474-byte PDF we made) 'When does Project Kestrel launch?' | agent run '...' --agent deep-research-preview-04-2026 --background | models list | image x --body '{"response_format":{"type":"image","image_size":"3K"}}' | image x --body '{"response_format":' | analyze -i does-not-exist.pdf q All ~0.54 s each. 9/9 completed inside the no-network namespace, 0 proxy hits; 7/7 valid previews parse as JSON; header X-Goog-Api-Key shows [REDACTED]; fake key string found 0 times in any stdout/stderr. Invalid inputs: missing file -> exit 2 (CLI_VALIDATION); broken JSON -> exit 2; image_size "3K" (README lists only 512/1K/2K/4K) -> ACCEPTED, exit 0, previewed as a request. Keychain: dry-runs with key (generate, image --body, agent run) and without key (generate, image, analyze, models list): 0 connects to the D-Bus socket. Positive control: plain 'gemini-api whoami' (no dry-run) connected to the socket once each time; 'whoami --dry-run' did not. So the detector works and dry-run skips the keychain.