Skip to content

OAuthProxy: _refresh_locks dict grows unboundedly with token churn #3866

@strawgate

Description

@strawgate

Description

OAuthProxy._refresh_locks (line 559 of proxy.py) creates an anyio.Lock per upstream_token_id to prevent concurrent refresh races. Entries are never removed, so the dict grows monotonically with every distinct token ID.

Impact

Growth rate is one entry per unique user whose token has been refreshed. Each entry is ~200 bytes (lock object + string key). In a typical deployment this is bounded by the user base, so it's unlikely to cause issues unless the proxy runs for a very long time with high user churn.

Reproduction

# After N distinct users refresh tokens:
len(proxy._refresh_locks)  # N entries, never decreasing

Possible fixes

  • Cap with an OrderedDict + LRU eviction (simplest, minor race window on evicted entries)
  • Periodic sweep of unheld locks (anyio.Lock doesn't expose held state)
  • Accept the current behavior and document the growth bound

Found during an audit of unaddressed review feedback on merged PRs (originally flagged by Codex bot on PR #3713).

Metadata

Metadata

Assignees

No one assigned

    Labels

    authRelated to authentication (Bearer, JWT, OAuth, WorkOS) for client or server.bugSomething isn't working. Reports of errors, unexpected behavior, or broken functionality.serverRelated to FastMCP server implementation or server-side functionality.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions