# RPC Enumeration — Antigravity CLI 'agy' v1.0.2 Language Server (gRPC)

Date: 2026-05-24T13:36:24Z
Tester: <REDACTED-RESEARCHER>
Authorized: Google Bug Hunters / Google VRP

## Setup
- agy version: 1.0.2 (PATH=/Users/<REDACTED-USER>/.local/bin/agy)
- Launch: `script -q /dev/null agy` (interactive mode, backgrounded under tty wrapper)
- LS gRPC HTTPS port (this run): 59498
- LS HTTP port: 58942
- Log: ~/.gemini/antigravity-cli/log/cli-*.log line "Language server listening on random port at <N> for HTTPS (gRPC)"

## Auth surface
- TLS cert: self-signed (curl -k required)
- Authorization header: NONE expected or enforced
- x-codeium-csrf-token header: NOT REQUIRED (omitted from all requests below)
- Origin header: any value accepted (server returns body regardless)
- OPTIONS preflight: returns 204 with NO Access-Control-Allow-Origin header
  -> Browser-origin attacks blocked by browser CORS, BUT any same-user CLI/tool/script reads freely

## Reachable methods (return data without ANY auth)
Method                                            | grpc-status | size | meaning
--------------------------------------------------+-------------+------+-----------------
exa.language_server_pb.LanguageServerService/Heartbeat          | 0   | sm | OK no-op
exa.language_server_pb.LanguageServerService/RunCommand         | 0/2 | var| EXECUTES shell command — returns stdout
exa.language_server_pb.LanguageServerService/ReadFile           | 2   | -  | "uri: '': unknown uri scheme" — handler reached, needs URI arg
exa.language_server_pb.LanguageServerService/WriteFile          | 2   | -  | Same — handler reached
exa.language_server_pb.LanguageServerService/SearchFiles        | 0   | 0  | Reached, returns empty for empty query
exa.language_server_pb.LanguageServerService/ReadDir            | 2   | -  | Reached, needs URI
exa.language_server_pb.LanguageServerService/GetTokenBase       | 0   | 36 | Returns server identity / token base data
exa.language_server_pb.LanguageServerService/HasAuthToken       | 9   | -  | Reached, may indicate token state
exa.language_server_pb.LanguageServerService/FetchUserInfo      | 0   | 30 | Returns user info bytes
exa.language_server_pb.LanguageServerService/GetProfileData     | 0   | 4399 | LEAKS Google account profile photo (base64 JPEG)
exa.language_server_pb.LanguageServerService/GetWorkspaceInfos  | 0   | 108| LEAKS user's open workspace paths (incl ~ and ~/.gemini)
exa.language_server_pb.LanguageServerService/GetAvailableModels | 0   | 50371 | LEAKS full model + experiment config (gpt-oss-120b, gemini-3.1, cascade flags...)
exa.language_server_pb.LanguageServerService/GetAllPlugins      | 0   | small | List of installed plugins
exa.language_server_pb.LanguageServerService/GetMcpServerStates | 0   | small | MCP server state inventory
exa.language_server_pb.LanguageServerService/InstallCascadePlugin | 0 | small | Reached — empty body accepted (potential malicious-plugin install vector if non-empty body works)
exa.language_server_pb.LanguageServerService/ToggleMcpServer    | 2   | -  | "server '' not found in config" — handler reached
exa.language_server_pb.LanguageServerService/SkipBrowserSubagent| 2   | -  | "run state not found" — handler reached (permission-bypass primitive)
exa.language_server_pb.LanguageServerService/StartCascade       | 3   | -  | "CortexTrajectorySource is unspecified" — handler reached
exa.language_server_pb.LanguageServerService/StreamTerminalShellCommand | 2 | - | Streaming shell-command handler reached
exa.language_server_pb.LanguageServerService/AddTrackedWorkspace| 2/0 | - | Reached
exa.language_server_pb.LanguageServerService/RemoveTrackedWorkspace | 2 | - | Reached
exa.language_server_pb.LanguageServerService/OpenUrl            | 2   | -  | "url cannot be empty" — handler reached
exa.language_server_pb.LanguageServerService/RecordEvent        | 0   | small | Reached
exa.language_server_pb.LanguageServerService/GenerateSkillInstallationCL | 12 | - | "unimplemented: only available in Google environment"
exa.language_server_pb.LanguageServerService/LoginWithBrowser   | 9   | -  | failed_precondition (reached)

## Methods NOT found (HTTP 404):
GetSecretValue, GetGitHubAccessToken (not in 1.0.2 LanguageServerService — strings inventory must come from desktop/ApiServerService instead)
GetCsrfToken, GetUser, ExchangeAuthCodeForJwt, ExecutePython — not exposed on LS

## Wire format
- Protocol: gRPC-Web over HTTP/2 + TLS (self-signed cert)
- Content-Type: application/grpc-web+proto
- Frame: 1 byte flag (0x00 = data, 0x80 = trailer) + 4-byte BE length + proto body
- Trailer frame contains "grpc-status: N" and (optional) "grpc-message: ..."
