Skip to content

fix: get_token endpoint has no authentication — bootstrap problem #42

@manzil-infinity180

Description

@manzil-infinity180

What Exists

The MCP server exposes a get_token tool that issues a session-scoped JWT to any caller (#19). The token grants tool-level authorization for the session. Once a token is issued, all subsequent tool calls must include it.

The server binds to localhost (stdio mode or 127.0.0.1 in HTTP mode), which limits the attack surface to local processes.

What's Missing

get_token has no authentication. Any MCP client that connects to the server can call get_token and receive a valid JWT with full policy scopes. This is the classic bootstrap problem: you need auth to get auth, but the auth-dispensing endpoint is unprotected.

Attack scenario (local attacker):

  1. Attacker discovers the MCP server port (e.g., by scanning localhost)
  2. Attacker connects and calls get_token before the legitimate Claude Code client
  3. Attacker receives a valid JWT and can call any tool the policy allows
  4. When the legitimate client calls get_token, a second token is issued (both are valid)

Mitigating factors:

  • Stdio mode (default): Only the process that spawned the server has stdin/stdout access. This is secure.
  • HTTP/SSE mode: Binds to localhost, so only local processes can connect. The attack window is small.

Proposed Fix

Option A: PID verification on get_token (strongest)

The server already does PID introspection for identity discovery. Extend this to get_token:

  1. On get_token call, get the connecting client's PID via SO_PEERCRED (Unix socket) or TCP port-to-PID mapping
  2. Verify the PID matches the expected agent process (e.g., Claude Code binary)
  3. Only issue tokens to verified agent processes

This ties into #24 (identity discovery uses spoofable heuristics). A proper SO_PEERCRED implementation would solve both.

Option B: Bootstrap secret (simpler)

  1. On server start, generate a random bootstrap secret and write it to a file readable only by the agent's UID
  2. get_token requires the bootstrap secret as a parameter
  3. After first successful get_token, invalidate the bootstrap secret (one-time use)

Option C: Issue token automatically on initialize (simplest)

Instead of a separate get_token call, issue the JWT during the MCP initialize handshake and return it in the server capabilities. The client gets the token as part of connection setup — no separate unauthenticated endpoint.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsecuritySecurity vulnerability or concern

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions