Skip to content

auth: a rolled-back Chrome marker reports as a network problem, and locks the profile out of any GOOGLE_SESSION_ONLY fallback #796

Open

Description

@ffroliva

Found during the /gflow:predict audit for #791. Not yet reproduced end-to-end — the chain is read from code, and the last leg is macOS-only. Filed because it changes how #791's fix must be triggered.

The chain

  1. A failed login rolls the Chrome marker back: auth/real_chrome.py:433-434 unlinks .gflow_browser_strategy when not verified and not marker_preexisted. Correct by itself, and deliberately scoped to a first login on a fresh profile.
  2. The next gflow auth status on macOS hits Keychain decryption failure → falls back to the Playwright cookie reader (auth/cookies.py:196).
  3. That reader is marker-gated: cookies.py:139-147 raises SecurityError when channel_for_profile(profile_dir) is not chrome. The marker was just unlinked, so it is not.
  4. SecurityError is not a PermissionError, so it escapes get_chrome_cookie_snapshot's normalization and is flattened to VERIFICATION_ERROR.
  5. The user is told to "check network connectivity" — for a marker-state problem on their own disk, with the network fine.

Why it matters beyond the bad message

On an already-rolled-back profile the outcome is VERIFICATION_ERROR, not GOOGLE_SESSION_ONLY. Any migrated-host fallback keyed only on GOOGLE_SESSION_ONLY — including the one proposed in #793 — therefore never runs on exactly the profiles that have already failed once. This is the argument for widening the trigger to {GOOGLE_SESSION_ONLY, VERIFICATION_ERROR}, or for making the migrated probe a peer oracle rather than a fallback.

It may also explain the inconsistency in #791, where the reporter quotes both outcome=google_session_only and the string "No sign-in detected" (which is NO_SESSION, verification.py:69) — two different profile states across five attempts.

What would settle it

On macOS, on a fresh profile: fail a login once, then run GFLOW_CLI_LOG_LEVEL=DEBUG gflow auth status and check whether the outcome is VERIFICATION_ERROR with a SecurityError underneath. Related: #768 (macOS Keychain modes differ between the real-Chrome login and the Playwright readers) — same OS, adjacent mechanism.

Suggested fix direction

Give SecurityError from the marker gate its own outcome or at minimum its own remediation string — "this profile's browser-strategy marker is missing; re-run gflow auth login --browser chrome" is actionable, "check network connectivity" is not.

Refs #791, #768

Activity

  1. ffroliva commented on Sep 12, 2026

    @ffroliva
    OwnerAuthor

    Partially fixed on develop in #797 (4d4ea3df).

    Landed: a distinct PROFILE_MARKER_MISSING outcome. The marker gate's SecurityError is no longer flattened into VERIFICATION_ERROR, so the user gets "this profile is missing its Chrome-strategy marker" plus gflow auth login --browser chrome instead of "check network connectivity". Mirrored on the MCP twin as HTTP 409 / retryable: false — neither a network blip (503, retry) nor a dead session (401, re-login) describes a marker that will not reappear on its own.

    Two existing tests were updated because they encoded the old classification; one of them turned out to be a near-duplicate that stopped at the marker gate rather than exercising the decryption path its name promised, so it now writes the marker and fails the fallback instead.

    Staying open, and why. The chain is still only verified from code and offline tests. Its live trigger is a cookie-store decryption failure, which does not occur on Windows/DPAPI — it is the macOS Keychain case (#768), and there is no Mac here. Per this repo's Iron Law that is a named external blocker, so this is Refs, not Closes.

    To close it, someone on macOS needs to: fail a login once on a fresh profile, then run GFLOW_CLI_LOG_LEVEL=DEBUG gflow auth status and confirm the outcome is now profile_marker_missing rather than verification_error.

    Adjacent finding, deliberately not fixed here. A synthetic attempt to force the path (a deliberately corrupt cookie store) produced sqlite3.DatabaseError, which is not normalized to PermissionError, so it bypasses the marker gate entirely and still prints "check network connectivity". Same misdirection class, different trigger — a corrupt or locked local file reported as a network fault. Left alone rather than widening the fix's scope.

  2. ffroliva commented on Sep 16, 2026

    @ffroliva
    OwnerAuthor

    Reproduced live — and confirmed that #791 is the trigger

    This issue was filed as "not yet reproduced end-to-end — the chain is read from code." It is reproduced now, on 2026-09-16, with a Google Workspace account on released 0.76.0. Windows, --browser chrome, real Chrome.

    The chain, measured

    gflow auth login --profile flavio.oliva --browser chrome:

    {"event": "auth_login_browser_closed_by_user", "cli_version": "0.76.0"}
    {"event": "auth_chrome_marker_rolled_back", "outcome": "google_session_only"}
    {"event": "auth_flow_session_unverified", "outcome": "google_session_only"}
    [exited with code 8]
    

    Immediately afterwards, on disk:

    channel_for_profile(profile_flavio.oliva) -> None
    profile contents: only .gflow_acl_v1 — the chrome marker is gone
    

    So the rollback at real_chrome.py:433-434 fired exactly as this issue predicted, on a profile the user explicitly created with --browser chrome. Its own comment states the cost: "silently downgrading generation to bundled Chromium."

    The trigger is #791, not a network problem

    outcome=google_session_only — labs' NextAuth session is simply never minted for this migrated account. Nothing was unreachable; the endpoint answered, with no session. That is #791, and it makes the rollback fire on every login attempt for an affected account, not as an edge case.

    The outcome field added for this issue is what made the distinction legible in the log — it separated "the probe endpoint was unreachable" from "genuinely signed out", and here it says neither: the session is absent while the account is perfectly usable.

    Fixing #791 prevents this entirely

    Same profile, same cookies, untouched on disk — only the code differed (#793's migrated-host fallback):

    released 0.76.0 with the #791 fallback
    verification auth_flow_session_unverified auth_flow_session_verified
    marker rolled back yes no
    channel_for_profile None chrome
    exit code 8 0

    The rollback is gated on not verified. When verification succeeds it never runs, so this issue does not fire at all.

    What that means for this issue's scope

    Two separable questions, and it is worth deciding which this issue owns:

    1. Should a failed verification roll the marker back at all? The rollback assumes a failure means "this profile is not really a chrome profile". auth: login verification never passes for accounts migrated to flow.google.com (labs NextAuth absent → GOOGLE_SESSION_ONLY forever) #791 shows a failure can also mean "Flow moved hosts and our oracle did not follow" — where the profile is a chrome profile and downgrading it is wrong. A rollback that fires on the wrong premise is worse than none, because it is silent and permanent.

    2. Should it be recoverable? Today the user's only route back is another gflow auth login, which on an affected account fails the same way and rolls it back again — a loop with no exit until auth: login verification never passes for accounts migrated to flow.google.com (labs NextAuth absent → GOOGLE_SESSION_ONLY forever) #791 is fixed.

    The macOS leg of the original chain remains unverified; this reproduction is Windows.

  3. added a commit that references this issue on Sep 16, 2026
  4. added 3 commits that reference this issue on Oct 25, 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

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions