Skip to content

fix(reviewer): never post agy's OAuth login prompt to a PR - #332

Merged
doublegate merged 1 commit into
mainfrom
fix/agy-reviewer-auth-prompt-guard
Jul 30, 2026
Merged

fix(reviewer): never post agy's OAuth login prompt to a PR#332
doublegate merged 1 commit into
mainfrom
fix/agy-reviewer-auth-prompt-guard

Conversation

@doublegate

Copy link
Copy Markdown
Owner

Summary

The Antigravity (agy) PR reviewer leaked its interactive Google OAuth login flow into a public PR comment. This hardens the reviewer so that can never happen again — a change shared byte-identical across the reviewer template and all three Rusty* repos.

What happened

On PR #330 (a routine Dependabot bump), the github-actions reviewer posted an "Authentication required" comment containing a live-shaped accounts.google.com/o/oauth2/... authorization URL, a "paste the authorization code here" prompt, and an "authentication failed or timed out" tail. That happens when agy's cached Google OAuth session lapses on the self-hosted runner: agy --print emits its interactive login flow to stdout instead of a review. The text is non-empty, so have_text() classified it as a valid review and the script posted it verbatim.

The offending comment has already been deleted from #330.

The fix (defense in depth)

  • is_auth_prompt() (new helper) — detects agy's interactive-login signature (the OAuth endpoint URL + agy's own prompt strings). Keyed on runtime strings a genuine review never emits, so a review that merely discusses authentication is not misclassified.
  • Layer 1 — retry loop: an auth-prompt capture is rejected as a hard, non-retryable failure (re-auth is a human action; retrying only thrashes the backoff). The capture is blanked, and a dedicated post-loop branch exits non-zero with an actionable "re-authenticate agy on the runner host" message.
  • Layer 3 — pre-post guard: immediately before gh pr comment, if the assembled body still trips the signature, refuse to post and fail the job. Last line of defense — a public comment must never carry an OAuth URL, whatever upstream does.

Behavior on a healthy, authenticated runner is unchanged: a real review never matches, so it posts exactly as before. Only the lapsed-session path changes — from "leak the OAuth URL" to "fail loudly in the job log, post nothing."

Verification

  • bash -n clean.
  • is_auth_prompt() validated against the exact leaked comment text (matches → blocked), a benign review that discusses "authentication" (no match → posts), and empty output (no match).
  • Synced byte-identical (same sha256) across the template and RustyNES / RustySNES / RustyN64.

Note for the maintainer

The runner's agy OAuth session is currently lapsed (that is why the prompt appeared). Reviews will resume once agy is re-authenticated on the runner host; until then this change makes the reviewer fail cleanly instead of leaking. Companion PRs sync the same fix into RustySNES and RustyN64.

🤖 Generated with Claude Code

When agy's cached Google OAuth session lapses on the self-hosted runner,
`agy --print` emits its INTERACTIVE login flow to stdout instead of a
review -- a live-shaped `accounts.google.com/o/oauth2/...` authorization
URL plus a "paste the authorization code here" prompt and an
"authentication failed or timed out" tail. That text is non-empty, so
`have_text()` classified it as a valid review and the script posted it
verbatim as a public PR comment. Incident: it landed on PR #330 (a
Dependabot bump) as a "github-actions" review comment carrying the OAuth
URL -- noise, phishing-shaped content, and an advertisement that the
runner's auth had dropped. That comment has been removed.

Root cause: the capture pipeline had no notion of "agy produced output,
but the output is an auth prompt, not a review." `have_text()` only
checks for non-whitespace bytes.

Fix -- two independent layers, plus a helper:

  * is_auth_prompt() (new): true when a captured file carries agy's
    interactive-login signature -- the accounts.google.com OAuth endpoint
    URL, "paste the authorization code", "Authentication required. Please
    visit", "Waiting for authentication", or "authentication failed or
    timed out". Keyed on agy runtime strings a genuine review never
    emits, so a review that merely discusses "authentication" is not
    misclassified (verified against a benign review sample).

  * Layer 1 (retry loop): after CR-normalizing each attempt's capture and
    before the have_text() success break, reject an auth-prompt capture as
    a hard, NON-retryable failure. Re-auth is a human action on the runner
    host, so retrying only thrashes the backoff. Blank the capture (so no
    later path can post it), set auth_failed=1, and break. A dedicated
    post-loop branch then exits non-zero with an actionable message,
    ahead of the generic empty-output path.

  * Layer 3 (pre-post): a final hard guard immediately before
    `gh pr comment` -- if the fully assembled body still trips the
    auth-prompt signature, refuse to post and fail the job. This is the
    last line of defense: a public PR comment must never carry an OAuth
    URL regardless of any upstream change to body assembly.

Behavior on a healthy, authenticated runner is unchanged: a real review
never matches is_auth_prompt, so it posts exactly as before. Only the
lapsed-session path changes -- from "leak the OAuth URL" to "fail loudly
in the job log, post nothing." Syntax-checked (`bash -n`) and the
signature validated against the exact leaked comment text, a benign
authentication-discussing review, and empty output.

Synced byte-identical across the shared reviewer template and RustyNES /
RustySNES / RustyN64 (single source of truth).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@doublegate, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 39 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6e83fb8e-4244-4263-90bf-a2c7b9322709

📥 Commits

Reviewing files that changed from the base of the PR and between a1df7b9 and b5bb6f6.

📒 Files selected for processing (1)
  • scripts/agy-review.sh

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

Antigravity review (Gemini via Ultra)

This PR adds detection logic (is_auth_prompt) to scripts/agy-review.sh to prevent agy from posting interactive Google OAuth login prompts as public PR comments when runner authentication lapses.

Blocking issues

None found.

Suggestions

  • False positive risk on auth-related PRs (scripts/agy-review.sh#L29-L33): Matching broad substrings like accounts.google.com/o/oauth2 or Authentication required. Please visit will trigger false positives if a PR diff or review discussion legitimately includes OAuth endpoint URLs or login error messages. Consider requiring a combination of multiple prompt signatures (e.g., both the OAuth URL AND "paste the authorization code") before flagging the output as a login prompt.
  • Redundant fallback guard on $body_file (scripts/agy-review.sh#L511): Line 436 already truncates $out_file and sets auth_failed=1, which causes the script to exit 1 at line 461 before $body_file is ever constructed. The check on line 511 will only ever trigger if static header/footer wrapper templates themselves contain auth prompt strings.

Nitpicks

  • Variable declaration alignment (scripts/agy-review.sh#L119): auth_failed=0 is inserted between cleanup path pre-declarations and agy_refs_created. Group script state flags separately from file cleanup handles.

Automated first-pass review by agy on a self-hosted runner -- not a human review.

@doublegate

Copy link
Copy Markdown
Owner Author

@coderabbitai Full Review

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.


Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 40 minutes.

@doublegate
doublegate merged commit 5a3cf41 into main Jul 30, 2026
23 of 24 checks passed
@doublegate
doublegate deleted the fix/agy-reviewer-auth-prompt-guard branch July 30, 2026 04:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant