Skip to content

CLI stored-auth refresh write-back can overwrite a concurrent same-server OAuth update #2574

Closed

Description

@cliffhall

Problem

refreshStoredAuthToken in clients/cli/src/cli.ts (the --use-stored-auth refresh path) reads the OAuth state snapshot, runs the refresh grant over the network, and then writes back with writeOAuthSections(statePath, snapshot, { servers: [key] }). That call merges at whole-servers[url] granularity: the server entry it writes is built from the snapshot taken before the network round trip.

So a same-server update that lands during the refresh is overwritten by the stale entry. For example, a web-inspector OAuth flow that adds another issuer slot, changes activeIssuer, or saves new tokens is lost, and that issuer's credentials are erased.

This predates #2517. Before that fix the write-back was already { ...found.state, tokens } from the pre-request snapshot. Copilot raised it on #2572, where it was declined as out of scope for that PR.

Expected

The refresh write-back updates only the refreshed issuer slot's tokens, against the fresh on-disk server entry, inside the state-file lock. One way to do that is an atomic server-entry updater in core/auth/node/oauth-persist-file.ts: lock, fresh read, apply (entry) => entry', split secrets, write.

Reproduce (by inspection)

  1. Start --use-stored-auth against a server whose stored refresh token is valid, with a slow token endpoint.
  2. While the grant is in flight, complete a web-inspector OAuth flow for the same server URL with a different authorization server.
  3. After the CLI finishes, the web flow's issuer slot and activeIssuer change are gone.

Priority: Medium (6). Severity 2: a narrow race that needs a concurrent same-server write during the refresh round trip, and the damage is recoverable by re-authorizing. Urgency 2: wanted eventually. Bonuses: +1 bug, +1 milestoned.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingv2Issues and PRs for v2

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions