From ea16f86130291042486ba3c10640e73b63772d27 Mon Sep 17 00:00:00 2001 From: bitkyc08-arch Date: Tue, 18 Aug 2026 20:02:33 +0900 Subject: [PATCH] fix(antigravity): drop synthetic x-goog-api-client header on onboarding Re-applies the remaining half of PR #1889 onto current dev: the ide_version fix already landed, so this removes only the fabricated x-goog-api-client header from the onboardUser request and retires the now-unused ANTIGRAVITY_GOOG_API_CLIENT_UA constant. The real Antigravity client does not send this header, so emitting it was a fingerprint mismatch. Credit: PR #1889 (issue #1836). --- src/adapters/client-fingerprint.ts | 2 -- src/oauth/google-antigravity.ts | 4 ++-- tests/client-fingerprint.test.ts | 5 ----- tests/google-antigravity-oauth.test.ts | 9 ++++++++- tests/google-antigravity-wire.test.ts | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/adapters/client-fingerprint.ts b/src/adapters/client-fingerprint.ts index e01880a938..2bf5b11862 100644 --- a/src/adapters/client-fingerprint.ts +++ b/src/adapters/client-fingerprint.ts @@ -45,8 +45,6 @@ export function claudeCodeSessionId(token: string | undefined): string { export const ANTIGRAVITY_IDE_VERSION = "2.5.5"; const ANTIGRAVITY_IDE_CLIENT_NAME = "aidev_client"; const ANTIGRAVITY_IDE_PLATFORM = "windows/amd64"; -/** Secondary Google API client UA the Antigravity client library reports. */ -export const ANTIGRAVITY_GOOG_API_CLIENT_UA = "google-api-nodejs-client/10.3.0"; /** * Real Antigravity IDE User-Agent format, decompiled from 2.5.5 Go LS (`setHeaders` @ `0x1018fbe00`): diff --git a/src/oauth/google-antigravity.ts b/src/oauth/google-antigravity.ts index cc5d6b1938..be81b55de5 100644 --- a/src/oauth/google-antigravity.ts +++ b/src/oauth/google-antigravity.ts @@ -12,7 +12,7 @@ import { OAuthCallbackFlow, type OAuthCallbackFlowOptions } from "./callback-server"; import { generatePKCE } from "./pkce"; import type { OAuthController, OAuthCredentials } from "./types"; -import { antigravityUserAgent, ANTIGRAVITY_GOOG_API_CLIENT_UA, ANTIGRAVITY_IDE_VERSION } from "../adapters/client-fingerprint"; +import { antigravityUserAgent, ANTIGRAVITY_IDE_VERSION } from "../adapters/client-fingerprint"; const CLIENT_ID = process.env.GOOGLE_ANTIGRAVITY_CLIENT_ID || "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com"; @@ -110,7 +110,7 @@ async function onboardProject(accessToken: string, signal?: AbortSignal): Promis if (signal?.aborted) throw signal.reason ?? new Error("Antigravity onboarding aborted"); const response = await fetch(`${DAILY_API}/${API_VERSION}:onboardUser`, { method: "POST", - headers: { Authorization: `Bearer ${accessToken}`, Accept: "*/*", "Content-Type": "application/json", "User-Agent": antigravityUserAgent(), "x-goog-api-client": ANTIGRAVITY_GOOG_API_CLIENT_UA }, + headers: { Authorization: `Bearer ${accessToken}`, Accept: "*/*", "Content-Type": "application/json", "User-Agent": antigravityUserAgent() }, // `ide_version` is a version, not a User-Agent. `antigravityUserAgent()` returns the whole // header — `antigravity/ide/2.5.5 (aidev_client; os_type=...; arch=...)` — so onboarding was // sending a parenthesized UA string in a field the real client fills with `2.5.5`. It is a diff --git a/tests/client-fingerprint.test.ts b/tests/client-fingerprint.test.ts index 9f681fdb51..70487f60b3 100644 --- a/tests/client-fingerprint.test.ts +++ b/tests/client-fingerprint.test.ts @@ -1,7 +1,6 @@ import { describe, expect, test } from "bun:test"; import { ANTIGRAVITY_IDE_VERSION, - ANTIGRAVITY_GOOG_API_CLIENT_UA, CLAUDE_CODE_HEADERS, antigravityUserAgent, claudeCodeSessionId, @@ -56,10 +55,6 @@ describe("client fingerprint — helpers", () => { } }); - test("secondary google api client UA is pinned", async () => { - expect(ANTIGRAVITY_GOOG_API_CLIENT_UA).toMatch(/^google-api-nodejs-client\/[\d.]+$/); - }); - test("claude session id is a stable v4-shaped uuid per token", async () => { const a = claudeCodeSessionId("tok-abc"); const b = claudeCodeSessionId("tok-abc"); diff --git a/tests/google-antigravity-oauth.test.ts b/tests/google-antigravity-oauth.test.ts index c8fd1337e3..34938d5eeb 100644 --- a/tests/google-antigravity-oauth.test.ts +++ b/tests/google-antigravity-oauth.test.ts @@ -38,7 +38,14 @@ describe("antigravity project discovery", () => { test("falls back to onboardUser poll loop (not-done then done)", async () => { let onboardCalls = 0; - routeFetch((url) => { + routeFetch((url, init) => { + if (url.includes(":onboardUser")) { + // #1889: the synthetic x-goog-api-client header is dropped from onboarding — the real + // Antigravity client does not send it, so emitting it was a fingerprint mismatch. + const headers = (init?.headers ?? {}) as Record; + expect(headers["x-goog-api-client"]).toBeUndefined(); + expect(headers["User-Agent"]).toMatch(/^antigravity\/ide\//); + } if (url.includes(":loadCodeAssist")) return new Response(JSON.stringify({}), { status: 200 }); // no project if (url.includes(":onboardUser")) { onboardCalls++; diff --git a/tests/google-antigravity-wire.test.ts b/tests/google-antigravity-wire.test.ts index b7274aed31..a0944c99bb 100644 --- a/tests/google-antigravity-wire.test.ts +++ b/tests/google-antigravity-wire.test.ts @@ -63,7 +63,7 @@ describe("antigravity CCA envelope", () => { ); // The literal "antigravity" giveaway UA must no longer be sent. expect(req.headers["User-Agent"]).not.toBe("antigravity"); - // x-goog-api-client is NOT sent on runtime requests (CLIProxyAPI only uses it during onboarding). + // x-goog-api-client is never sent — not on runtime requests, and (since #1889) not on onboarding either. expect(req.headers["x-goog-api-client"]).toBeUndefined(); // sessionId lives only at request.sessionId (no top-level / snake_case duplicate). expect(env.request.sessionId).toMatch(/^-/);