Skip to content

Recover expired Grok sessions through the CLI owner - #3497

Draft
audreyt wants to merge 2 commits into
steipete:mainfrom
audreyt:fix/grok-session-recovery
Draft

Recover expired Grok sessions through the CLI owner#3497
audreyt wants to merge 2 commits into
steipete:mainfrom
audreyt:fix/grok-session-recovery

Conversation

@audreyt

@audreyt audreyt commented Sep 8, 2026

Copy link
Copy Markdown

Status: draft — credential-owner coordination gate remains

Integrated successor to #3473. This is not the standalone refresher again: the production OAuth fetch path now performs recovery, and a real CLI-owned renewal plus billing recovery has been exercised.

Do not merge yet. Happy-path renewal and subsequent CLI reuse are proven. The credential owner's concurrent account-change/logout contract is not cleared for release. Read-side checks cannot establish persistence safety inside another process. Owner-side findings are being kept out of public reproducer material in accordance with xAI's security reporting policy.

Implementation / ownership boundary

  • The CLI remains the only refresh-token consumer and auth.json writer. CodexBar does not POST to an OIDC token endpoint or save credentials.
  • An expired xAI OIDC record in the production OAuth strategy invokes grok agent --leader stdio, then ACP _x.ai/auth/getBearerToken. The shared owner is separate from the short-lived probe client.
  • Check the captured account/generation before requesting recovery. Afterward, reload the CLI-written record and require an unexpired token matching the export, scope, user, email, team, principal, issuer, and client.
  • Billing, bearer fallback, identity, and subscription enrichment all share the validated post-recovery capture. Team identity-only fallback retains principal metadata.
  • Pasted tokens, browser cookies, legacy sessions, and explicit auth-source overrides are not silently migrated to this flow.
  • Stop logging raw inbound Grok RPC responses, since the new response carries a bearer token.

The read-side account/generation checks intentionally are not represented as a cross-process compare-and-swap or a guarantee about the CLI's own final write.

Real behavior proof (2026-09-08, official Grok 1.0.13 / 5e9a58528b76)

The initial live protocol probe caught a bug the original stub missed: x.ai/auth/getBearerToken returns -32601; _x.ai/auth/getBearerToken succeeds. The response also contains both the JSON-RPC result and the extension's nested result envelope. The updated regression failed with the old wire method, then passed after the correction.

For the live expiry exercise, only the existing auth record's expiry timestamp was temporarily marked expired under the CLI's file lock. No refresh token was copied into a second credential store. The real CLI contacted the real token service and persisted the renewed generation. The harness was guarded to restore only the expiry of an unchanged generation; no rollback was needed.

Redacted result from the newly built CodexBarCLI usage --provider grok --source oauth --json:

{
  "exit_code": 0,
  "elapsed_seconds": 2.776,
  "access_token_rotated": true,
  "refresh_token_rotated": true,
  "same_identity": true,
  "unexpired": true,
  "source": "grok-cli-proxy",
  "usage_present": true,
  "subscription_tier_present": true
}

A separate subsequent connection to the installed CLI exported the same persisted bearer and successfully called _x.ai/billing:

{
  "bearer_matches_auth_file": true,
  "cli_reused_existing_token": true,
  "cli_billing_supported": true,
  "cli_billing_result_present": true
}

This proves real token exchange, persistence by the owner, resumed billing, and CLI reuse after a locally forced expiry timestamp. It is not a claim that the server-side JWT expired naturally during the test, or that the owner-side concurrency gate passed. No tokens, account identifiers, or private transcripts are included here.

Validation

  • swift test --filter 'GrokAccountContextTests|GrokSessionRecoveryTests': 11 tests passed, including the real subprocess protocol fixture, Team recovery, account-switch/removal/generation rejection, and existing account-capture cases.
  • After merging current main (only CHANGELOG.md conflicted), swift test --filter Grok: 156 tests in 15 suites passed. The newly built production CLI also returned usage and subscription tier with no error.
  • Final integrated make check: passed, including SwiftFormat and strict SwiftLint (0 violations across 2,142 Swift files).
  • Full make test on the implementation commit: did not pass. The sharded run selected 1,035 selections in 87 groups and exited on a 180-second timeout in UsageStoreCachedTokenHydrationTests. The same selection also timed out at 180 seconds on unchanged base 0cb8c425e, after a clean rebuild in an isolated worktree with the same test-isolation environment. This timeout therefore reproduces without the Grok changes; the full suite is not reported as green.

Before marking ready

  • Resolve the credential owner's concurrent account-change/logout coordination guarantee. Do not infer that guarantee from the read-side tests or the happy-path runtime transcript.
  • Keep this PR in draft until that release gate is cleared.

Wire OAuth fetching to the shared CLI owner's ACP bearer export, then reload and validate the account before billing. Keep token exchange and auth.json writes out of CodexBar; preserve team identity and reject mismatching snapshots.

Use the required _x.ai/auth/getBearerToken wire prefix and nested extension result envelope. Verified real CLI 1.0.13 token rotation, successful OAuth billing, and subsequent CLI reuse. Focused regression tests and make check pass.

Draft-only: credential-owner concurrent account-change/logout coordination remains a release gate. Read-side guards do not prove cross-process persistence safety.
@clawsweeper

clawsweeper Bot commented Sep 8, 2026

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@audreyt audreyt mentioned this pull request Sep 8, 2026
@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Sep 8, 2026
@clawsweeper

clawsweeper Bot commented Sep 8, 2026

Copy link
Copy Markdown

Codex review: needs real behavior proof before merge. Reviewed September 8, 2026, 3:29 AM ET / 07:29 UTC.

ClawSweeper review

What this changes

The PR adds CLI-owned renewal of expired Grok credentials before OAuth usage fetching, validates the reloaded account, removes raw RPC response logging, and adds tests and documentation.

Merge readiness

Blocked before merge - 5 items remain

Keep open: this remains useful work absent from main, with credible live renewal evidence. The explicitly unresolved credential-owner concurrency guarantee still blocks release; no additional concrete patch defect was established.

Priority: P2
Reviewed head: d2f380876ca698a0f93125dae2f4647409705f80
Owner decision: Required. See Decision needed.

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) Focused implementation and credible happy-path proof are limited by the unresolved credential-authority contract.
Proof confidence 🦐 gold shrimp (3/6) Needs stronger real behavior proof before merge: Authority-chain proof required: the captured production CLI output credibly demonstrates real renewal, billing recovery, and subsequent CLI reuse with Grok 1.0.13 after locally forced expiry. Owner-side rejection of stale renewal during logout or account replacement before persistence and authenticated I/O remains expressly unproven. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Patch quality 🦐 gold shrimp (3/6) Security review found an item that needs attention.

Verification

Check Result Evidence
Real behavior Needs proof Needs stronger real behavior proof before merge: Authority-chain proof required: the captured production CLI output credibly demonstrates real renewal, billing recovery, and subsequent CLI reuse with Grok 1.0.13 after locally forced expiry. Owner-side rejection of stale renewal during logout or account replacement before persistence and authenticated I/O remains expressly unproven. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed 9 items Repository policy and scope: Read the complete root AGENTS.md. No nested AGENTS.md or matching maintainer-note files were found under the inspected Sources, Tests, docs, and .agents trees. Applied credential isolation, focused validation, and no unsolicited live-account probing guidance; this review ran no builds or tests.
Recovery remains absent from main and the latest release: Current main rejects expired credentials inside the OAuth billing closure without invoking renewal. The inspected v0.56.8 source has the same behavior. The related predecessor is closed unmerged, so it supplies no merged replacement.
Release source check: The latest supplied release, v0.56.8, rejects expired OAuth credentials before billing; it does not contain this recovery path.
Findings None None.
Security Needs attention Credential-owner final-write safety remains unverified: The new recovery call can cause CLI-owned renewal and persistence before CodexBar reloads the file. The PR explicitly leaves concurrent logout and account replacement uncleared; read-side rejection cannot prove the owner rejected stale authority before its final effects.

How this fits together

CodexBar’s Grok provider reads CLI credentials to fetch billing and subscription information for its usage display. This change asks the CLI to renew expired credentials, then validates the saved result before using it.

flowchart TD
 A[OAuth usage request] --> B[Read CLI credentials]
 B --> C{Expired credential?}
 C -->|No| F[Billing and subscription requests]
 C -->|Yes| D[CLI owns renewal and persistence]
 D --> E{Reloaded token and account match?}
 E -->|Yes| F
 E -->|No| G[Reject recovery]
 F --> H[Usage and account display]
Loading

Decision needed

Question Recommendation
Has the Grok credential owner established sufficient logout and account-replacement guarantees for CodexBar to enable automatic renewal? Retain the draft gate: Keep recovery unreleased until owner-approved, sanitized evidence establishes rejection of stale renewal before persistence and authenticated I/O.

Why: The author explicitly withholds release clearance pending private owner-side coordination; CodexBar’s read-side checks cannot settle the external process’s final-write contract.

Before merge

  • Add real behavior proof - Needs stronger real behavior proof before merge: Authority-chain proof required: the captured production CLI output credibly demonstrates real renewal, billing recovery, and subsequent CLI reuse with Grok 1.0.13 after locally forced expiry. Owner-side rejection of stale renewal during logout or account replacement before persistence and authenticated I/O remains expressly unproven. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
  • Resolve security concern: Credential-owner final-write safety remains unverified - The new recovery call can cause CLI-owned renewal and persistence before CodexBar reloads the file. The PR explicitly leaves concurrent logout and account replacement uncleared; read-side rejection cannot prove the owner rejected stale authority before its final effects.
  • Resolve merge risk (P1) - A renewal already in flight may outlive logout or account replacement inside the CLI owner; the available evidence does not establish that stale authority is rejected before credential persistence and subsequent authenticated I/O.
  • Complete next step (P2) - Keep the PR draft until the credential-owner concurrency gate is cleared with sanitized final-effect evidence. Redact tokens, account identifiers, IP addresses, and private endpoints; retain sensitive details in the private security channel. Updating the PR body should trigger re-review; otherwise ask a maintainer to comment @clawsweeper re-review.
  • Resolve maintainer decision - Resolve the maintainer decision shown above before merge.

Findings

  • [medium] Credential-owner final-write safety remains unverified — Sources/CodexBarCore/Providers/Grok/GrokSessionRecovery.swift:34
Agent review details

Security

Needs attention: Raw bearer response logging is removed, but credential-owner concurrency remains a release-blocking authority uncertainty.

Review metrics

Metric Value Why it matters
Production and test growth production +91/-5, tests +133/-2 Production growth implements CLI recovery and capture reuse; tests cover protocol decoding and account-change rejection.

Merge-risk options

Maintainer options:

  1. Wait for the credential-owner guarantee (recommended)
    Keep this draft pending sanitized final-effect evidence for logout and account replacement during renewal.
  2. Leave renewal disabled
    Defer the recovery integration if the owner cannot invalidate stale renewal safely.

Technical review

Best possible solution:

Retain CLI-owned renewal and the single validated account capture, with an owner-approved concurrency contract that prevents stale credentials from surviving logout or account replacement.

Do we have a high-confidence way to reproduce the issue?

Not applicable as an established-behavior bug: main intentionally rejects expired OAuth credentials, and this PR adds automatic recovery. The supplied live output demonstrates the new happy path, not the unresolved concurrency case.

Is this the best way to solve the issue?

Yes for the ownership design: reusing the CLI’s renewal owner avoids a second credential writer. Release safety remains conditional on that owner’s concurrent logout and account-replacement guarantees.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against c3f3ea1faf70.

Labels

Label justifications:

  • P2: Automatic recovery is a bounded improvement to Grok OAuth usage fetching.
  • merge-risk: 🚨 security-boundary: The new renewal call crosses into a credential-writing owner whose logout and account-replacement guarantees remain explicitly unproven.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦐 gold shrimp and patch quality is 🦐 gold shrimp.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: Authority-chain proof required: the captured production CLI output credibly demonstrates real renewal, billing recovery, and subsequent CLI reuse with Grok 1.0.13 after locally forced expiry. Owner-side rejection of stale renewal during logout or account replacement before persistence and authenticated I/O remains expressly unproven. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Evidence

Security concerns:

  • [medium] Credential-owner final-write safety remains unverified — Sources/CodexBarCore/Providers/Grok/GrokSessionRecovery.swift:34
    The new recovery call can cause CLI-owned renewal and persistence before CodexBar reloads the file. The PR explicitly leaves concurrent logout and account replacement uncleared; read-side rejection cannot prove the owner rejected stale authority before its final effects.
    Confidence: 0.98

What I checked:

  • Repository policy and scope: Read the complete root AGENTS.md. No nested AGENTS.md or matching maintainer-note files were found under the inspected Sources, Tests, docs, and .agents trees. Applied credential isolation, focused validation, and no unsolicited live-account probing guidance; this review ran no builds or tests. (AGENTS.md:1, d2f380876ca6)
  • Recovery remains absent from main and the latest release: Current main rejects expired credentials inside the OAuth billing closure without invoking renewal. The inspected v0.56.8 source has the same behavior. The related predecessor is closed unmerged, so it supplies no merged replacement. (Sources/CodexBarCore/Providers/Grok/GrokProviderDescriptor.swift:248, c3f3ea1faf70)
  • Release source check: The latest supplied release, v0.56.8, rejects expired OAuth credentials before billing; it does not contain this recovery path. (Sources/CodexBarCore/Providers/Grok/GrokProviderDescriptor.swift, 6ef82690b4a7)
  • Authority and dependency boundary: Recovery executes grok agent --leader stdio and requests its bearer export. It checks the original credential before that call and validates the reloaded token and identity afterward. This directly depends on the Grok CLI’s renewal and persistence contract; a post-call read cannot establish authorization at the CLI’s final write. (Sources/CodexBarCore/Providers/Grok/GrokSessionRecovery.swift:34, d2f380876ca6)
  • Authenticated final effect: The validated capture flows into billing and subscription enrichment. The billing transport constructs an Authorization bearer header and sends the request through the production HTTP transport. (Sources/CodexBarCore/Providers/Grok/GrokCreditsProxyFetcher.swift:26, d2f380876ca6)
  • Captured real behavior evidence: The supplied full PR body at sourceRevision 3a2ba212f1b69253b36879f17e50942eef0d89c0cead5f96362d3e2821d489ef reports the newly built production CLI exercising official Grok 1.0.13 after locally forcing the stored expiry timestamp. Redacted output records access/refresh token rotation, unchanged identity, resumed billing and subscription data, and subsequent CLI reuse. The body expressly excludes concurrent logout/account-change safety from this proof. (d2f380876ca6)

Likely related people:

  • Peter Steinberger: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
  • o.akimov: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Provide owner-approved, sanitized evidence that logout and account replacement invalidate in-flight renewal before persistence and authenticated I/O; keep sensitive reproducer details in the private security channel.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (1 earlier review cycle)
  • reviewed 2026-09-08T07:22:17.348Z sha dc4989b :: needs real behavior proof before merge. :: none

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. P2 Normal priority bug or improvement with limited blast radius. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant