Skip to content

fix(ai): antigravity-auth does not apply the blank-credential rule — whitespace keyring tokens are accepted, cached, and sent as a Bearer of spaces #1765

Open

Description

@dezren39

fix(ai): antigravity-auth does not apply the blank-credential rule — whitespace keyring tokens are accepted and sent

Summary

The repo's auth bridges share one rule, stated verbatim in the #1763 fix
(commit 0dd051a394, PR #1764): "A blank value is no credential (the
vibe-auth rule): trim, and treat whitespace-only as absent."
vibe-auth.ts
trims at every tier (:146 env, :154 file, :160 keyring), and #1763 extended
the rule to commandcode-auth.ts and claude-code-auth.ts with tests.

packages/ai/src/providers/antigravity-auth.ts — the fourth first-party
auth bridge — was not touched and applies the rule nowhere. Verified by
reading on main 2981dfd838:

Evidence

  1. Whitespace-only refresh token passes the shape check and is POSTed.
    antigravity-auth.ts:115 — if (!creds.token?.refresh_token) return reject(...) rejects only missing/empty values. A refresh token of
    " " passes, and refresh() sends it to
    https://oauth2.googleapis.com/token as refresh_token (:252), where
    it fails as an opaque invalid_grant instead of being read as "no
    credential stored".

  2. Whitespace-only access token is cached and sent as a Bearer.
    loadToken (:308): if (creds.accessToken && creds.expiryMs - Date.now() > 60_000) — a whitespace-only access_token from the
    keyring is truthy, so with a future expiry it is cached and returned;
    keyringAuth then emits authorization: \Bearer ${token.accessToken}``
    (:335) — literally a Bearer token of spaces, the exact failure fix(ai): commandcode + claude-code auth bridges accept whitespace-only credentials — a blank env var shadows commandcode's valid login file, and both bridges send a Bearer header of spaces #1763's
    title names for the sibling bridges.

  3. Whitespace-only access token from the token endpoint is accepted.
    refresh() (:274): if (!parsed.access_token) rejects only
    missing/empty; a whitespace-only access_token in a 200 response is
    cached and later sent as a Bearer per (2).

  4. No test pins any of this. packages/ai/test/provider/antigravity-auth.test.ts
    covers only refresh bounding (fix(ai): Antigravity token refresh fetch has no deadline, response body unbounded — check:bounded-http is red on main #1469) and client-secret candidates
    (antigravity: client-secret extraction (first GOCSPX match) stale for agy 1.4.11 — refresh fails invalid_client #1633); grep for trim|whitespace|blank in that file: 0 hits. The
    sibling bridges each gained explicit whitespace tests in fix(ai): commandcode + claude-code auth bridges accept whitespace-only credentials — a blank env var shadows commandcode's valid login file, and both bridges send a Bearer header of spaces #1763
    (claude-code-auth.test.ts, commandcode-auth.test.ts).

Why it matters

The keyring entry is written by an external binary (agy) and read back
verbatim; a corrupted or placeholder entry currently degrades into a
confusing upstream auth failure (or a spaces-only Bearer) instead of the
bridge's own clear "credential unavailable / unexpected shape" errors.
Consistency also matters for the doctrine in #1717: all *-direct bridges
should treat blank credentials identically, so fall-through and fail-closed
behavior is predictable across providers.

Acceptance criteria

Filed by new-issue-creator-opencode; sibling of closed #1763 (same rule,
bridge not covered there — deduped against open/closed search for
"blank credential whitespace" and "antigravity auth", 2026-11-05).

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    kind/testTest coverage, test infrastructure, or test-only fixes
    task/triageQueue packet kind: verify, reproduce, and route this item
    source/creatorFiled by the new-issue-creator job
    priority/normalOrdinary priority (the default)
    queue/queuedHas a queued task in the Supabase agent queue
    app/aiPackage: ai (pkgs/ or apps/ in this repo)
    effort/sSmall: expected under 2 hours of work
    on Nov 5, 2026
  2. dezren39 commented on Nov 5, 2026

    @dezren39
    Author

    🤖 Agent note · filed

  3. added
    queue/claimedA queue worker has claimed the task for this item
    work/assignedAn agent holds this item via the queue (claimed task)
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 5, 2026
  4. dezren39 commented on Nov 5, 2026

    @dezren39
    Author

    🤖 Agent note · handed off — task 10729 (queue repo-health-opencode-pilot, lane opencode-a)

    • Agent: queue worker (repo-worker-opencode)
    • Execution lane: opencode — checkpointed handed_off; the laptop claimant (opencode-claimant) launches the bound opencode session that drives this task to its terminal state.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    app/aiPackage: ai (pkgs/ or apps/ in this repo)area/typescriptTypeScript code areaeffort/sSmall: expected under 2 hours of workkind/bugSomething isn't working (prefixed form of the classic bug label)kind/testTest coverage, test infrastructure, or test-only fixespriority/normalOrdinary priority (the default)queue/claimedA queue worker has claimed the task for this itemsource/creatorFiled by the new-issue-creator jobstatus/in-progressActively being workedtask/triageQueue packet kind: verify, reproduce, and route this itemwork/assignedAn agent holds this item via the queue (claimed task)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions