Skip to content

auth.json: a token refresh can resurrect a signed-out session (deleteAuth race) #236

Description

@vreshch

Follow-up from cli#231 / cli#235 (config locking), characterized by the #235 adversarial verifier: 200 iterations of a sign-out (deleteAuth) racing an in-flight token refresh (mutateAuth) -> 94 sign-out-won / 106 resurrected / 0 corrupt.

Root cause (deeper than deleteAuth)

deleteAuth is lock-free, but making it locked only serializes the two ops - it does NOT stop resurrection. The actual cause: when a token refresh's mutateAuth re-reads a null (just-signed-out) auth.json, tryRefresh (src/lib/api.ts) falls back to the IN-MEMORY tokens and writes them back, resurrecting the session the user just ended.

Correct fix

Two parts:

  1. Route deleteAuth through withFileLock (make it async; the single caller setup.ts disconnect already awaits) - removes the torn window, deterministic ordering.
  2. In the refresh path, treat "disk read is null" as "signed out - do not resurrect": mutateAuth's refresh mutator should return null (skip the write) when the fresh disk read is null, instead of folding in-memory tokens. This is the part that actually kills resurrection.

Severity

LOW: no corruption, atomic writes throughout, resurrected content is the user's own freshly-refreshed valid tokens (never stale/foreign), sub-ms window, and it requires an explicit --disconnect racing a background refresh. The lost-update class #231 targeted is fully closed (0/90 with the lock); this is the correctly-scoped-out remainder.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions