Skip to content

fix(ai): agy GOCSPX scan can collect a truncated prefix at chunk boundaries — #1642's 'never truncated' guarantee fails for stable-boundary straddles #1822

Closed

Description

@dezren39

Finding

The chunked GOCSPX scan added by PR #1642 in packages/ai/src/providers/antigravity-auth.ts can add a truncated prefix of a secret run as a candidate, contradicting its own comment — a run that straddles the "stable region" boundary is matched truncated first, and only later matched whole. No test exercises a run straddling a chunk boundary.

Evidence

  • PR: fix(ai): antigravity secret extraction tries all GOCSPX candidates (#1633) #1642 "fix(ai): antigravity secret extraction tries all GOCSPX candidates (antigravity: client-secret extraction (first GOCSPX match) stale for agy 1.4.11 — refresh fails invalid_client #1633)", merged 2026-11-04T17:33:15Z, merge commit 94c4461, head 9070d62.
  • Current main 4d2d9bf, antigravity-auth.ts (blob b3145bb6f1b8, unchanged since the PR): :154 the scan reads the binary in 1 MiB chunks; :163-165 collect matches on stable = text.slice(0, -256) for non-flush calls; :171-177 the loop sets carry = text.slice(-256) and flushes the carry at EOF.
  • The comment at :158-162 claims matches are collected from the stable region "so a run split across a chunk boundary is matched whole, never as a truncated prefix". That holds only for a run that starts inside the last 256 chars. A run that starts at least 17 chars before the stable boundary (7 for GOCSPX- + the regex's {10,} minimum) and ends after it is matched by matchAll(/GOCSPX-[A-Za-z0-9_-]{10,}/g) in truncated form and added to runs in that form; the whole run is added only on the next chunk's pass, after the truncated one in scan order.
  • Candidate derivation (:~185-190) slices each run to its first 35 chars: a truncated run of 17-34 chars yields a bogus short candidate distinct from the real one, so the first refresh in a process spends an extra token-endpoint attempt on a candidate that can only be rejected invalid_client before trying the real secret (the winner cache masks this on later refreshes).
  • Test gap: the antigravity: client-secret extraction (first GOCSPX match) stale for agy 1.4.11 — refresh fails invalid_client #1633 tests in packages/ai/test/provider/antigravity-auth.test.ts use small single-chunk fixture binaries; no fixture places a GOCSPX run across a 1 MiB chunk boundary (or across the stable/carry boundary), so the claimed guarantee is untested.

Why it matters

The scan's correctness claim is false for exactly the boundary case it was written to handle. The practical cost today is one wasted invalid_client round-trip on a first refresh whenever a run straddles a boundary, plus a candidate list that does not match the documented invariant — and a future change that trusts the invariant (e.g. stopping at the first candidate, or capping candidate count) would turn the truncated entry into a real extraction failure.

Acceptance criteria

  • A test with a fixture binary whose GOCSPX run straddles a chunk/stable boundary (at several start offsets, including 17-34 chars of the run inside the stable region) asserts the candidate set contains the whole run and no truncated prefix.
  • collect no longer emits a match that ends exactly at the stable-region boundary (or an equivalent fix), and the :158-162 comment matches the implemented guarantee.
  • Existing antigravity-auth candidate tests (antigravity: client-secret extraction (first GOCSPX match) stale for agy 1.4.11 — refresh fails invalid_client #1633 layouts, non-invalid_client no-cycle) keep passing.

Agent: pr-diff-review-b; state: filed; run: 2026-11-06 03:18 CST; source PR: #1642; verified against main 4d2d9bf (antigravity-auth.ts read from contents API, blob b3145bb6f1b8).

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    task/triageQueue packet kind: verify, reproduce, and route this item
    priority/lowNice to have; do when convenient
    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
    work/assignedAn agent holds this item via the queue (claimed task)
    queue/claimedA queue worker has claimed the task for this item
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 6, 2026
  2. dezren39 commented on Nov 6, 2026

    @dezren39
    Author

    🤖 Agent note · picked up

  3. added
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 6, 2026
  4. 7 remaining items

  5. dezren39 commented on Nov 6, 2026

    @dezren39
    Author

    🤖 Agent note · triage verdict: CONFIRMED (stronger than filed)

    • Agent: queue worker (repo-worker-opencode), lane opencode-a
    • Session / ID: task 10960 (resume of the reproduced checkpoint left by the evaporated claim; monitor handoff 2026-11-06T10:52Z)
    • Found via: queue claim

    Reproduction re-run this shift on the laptop (probes ~/git/fleet/probe-1822.ts + probe-1822b.ts against the scan logic from main; code re-verified unchanged on current main a6d8ac0 — collect at antigravity-auth.ts still matches the stable region with no end-at-boundary guard):

    • stable-20, len47 (ends in carry region): runs=[20-char truncated] — whole=false, truncated=true
    • stable-10, len47 (below regex minimum in stable region): runs=[] — the whole run is LOST, not merely truncated
    • stable-20, len300 (ends in chunk 2): truncated only
    • stable-300, len400: truncated only
    • chunk-boundary straddle and fully-inside-stable controls: whole run collected correctly

    So #1642's 'matched whole, never as a truncated prefix' guarantee fails for stable-boundary straddles, and at offsets where the stable portion is below the regex minimum the run can be lost entirely under this chunking. Route: small_fix — collect must not emit a match ending exactly at the stable-region boundary, and the deferred run must be recovered whole later (including the lost-offset case); comment updated to the implemented guarantee; boundary tests at several offsets. Fix enqueued as a follow-up task (see next note / queue state).

  6. dezren39 commented on Nov 6, 2026

    @dezren39
    Author

    agent-note:v1 — follow-up fix enqueued: task 11018 (repo-health-opencode-pilot, dedupe repo-health:v1:fix:developing-today/opencode:issue:1822), packet hidden_files/10960-fix-packet-1822.json. Route per triage: suppress boundary-truncated emissions AND recover the whole run (carry back to the boundary-reaching run's start or equivalent) — dropping truncated matches alone would convert bogus-candidate cases into total loss.

  7. added
    queue/claimedA queue worker has claimed the task for this item
    work/assignedAn agent holds this item via the queue (claimed task)
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    and removed
    queue/claimedA queue worker has claimed the task for this item
    on Nov 6, 2026
  8. dezren39 commented on Nov 6, 2026

    @dezren39
    Author

    agent-note:v1 — state: PR #1843 open, task 11018 parked for review. Fix: collect defers any run reaching the stable-region boundary (and any sub-minimum fragment / partial GOCSPX- literal at the boundary) by carrying from the run's start, so it is matched whole on the next pass or final flush — never truncated, never lost. Tests: antigravity-auth 16 pass incl. 4 new >1MiB boundary fixtures (fail on pre-fix code); typecheck clean. Resume: disposition Codex findings on #1843, merge if sound.

  9. added a commit that references this issue on Nov 6, 2026
  10. removed
    queue/queuedHas a queued task in the Supabase agent queue
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    work/assignedAn agent holds this item via the queue (claimed task)
    on Nov 6, 2026
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)effort/sSmall: expected under 2 hours of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/lowNice to have; do when convenientsource/pr-diff-reviewFiled by the pr-diff-review jobtask/triageQueue packet kind: verify, reproduce, and route this item

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions