Skip to content

[Security][Medium] OAuth state has no TTL / single-use binding (replay) #46

@tembo

Description

@tembo

Severity: Medium
Area: Web — OAuth / replay

Location

web/src/lib/oauth-state.ts:60-163

Problem

The OAuth state is HMAC-signed but carries only a random nonce that is never recorded or checked server-side, and has no timestamp/TTL. A signed state (and, for native-MCP, the embedded PKCE verifier + DCR client_id) is therefore valid forever and reusable.

Why it matters

Combined with callbacks that only require session.user.id === state.userId, a leaked callback URL (referer header, logs, browser history) can be replayed by the same user indefinitely.

Suggested fix

Add an issued-at timestamp and reject states older than a few minutes. Ideally bind a one-time nonce stored server-side or in a short-lived cookie so each state is single-use.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsecuritySecurity vulnerability or hardeningseverity: mediumMedium severity

    Type

    No type
    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