MCPSafe.io
RegistryThreatsMethodologyDocsPricingScanSign in
MCPSafe.io

Security checks for MCP servers — public packages and private repos, fast or deep.

Legal

Privacy PolicyCookie PolicyTerms of ServiceSecurity disclosure

Resources

State of MCP SecuritySupportSystem statusMade in Germany 🇩🇪

© 2026 MCPSafe. All rights reserved.

GDPR — Privacy Policy
← Threat Catalog

Configuration & Environment

Session ID not bound to user identity

MEDIUMCWE: CWE-384Rule: MCP-266

MCP server uses `session_id` alone as the lookup key for session data — without binding to `user_id`, an attacker who guesses or obtains another user's session_id can impersonate them.

What it is

The official MCP security best practices require session keys of the form `<user_id>:<session_id>`. A bare `session_id` key means a single guess (or a single leaked id) grants access to that session's data. Binding to user_id eliminates the risk because guessing the session ID alone doesn't help — you'd need both the session_id AND the matching user_id, which the auth token supplies.

Why it matters for MCP

Multi-user MCP servers cache per-session state (queue items, intermediate results, partial completions). A bare-session_id key is the natural way to write the cache, but turns into a horizontal-privilege bug the moment a session_id leaks.

Vulnerable example

example.py
1
import boto3
2
from fastmcp import FastMCP
3
4
mcp = FastMCP("my-mcp")
5
sessions_table = boto3.resource("dynamodb").Table("sessions")
6
7
@mcp.tool()
8
def get_session(session_id: str) -> dict:
9
    return sessions_table.get_item(Key={"session_id": session_id})["Item"]

Secure example

example.py
1
import boto3
2
from fastmcp import FastMCP
3
4
mcp = FastMCP("my-mcp")
5
sessions_table = boto3.resource("dynamodb").Table("sessions")
6
7
@mcp.tool()
8
def get_session(user_id: str, session_id: str) -> dict:
9
    return sessions_table.get_item(
10
        Key={"user_id": user_id, "session_id": session_id}
11
    )["Item"]

How MCPSafe detects this

Per-occurrence in MCP-server-context files. Fires on DDB `get_item`/`put_item`/`update_item`/`delete_item`/`query` Key dict using `session_id` alone, container subscript (`sessions[session_id]`, `cache[session_id]`, `store[session_id]`, `queue[session_id]`), redis-style (`redis.{get,set,hget,hset}(session_id)`), or generic `.get`/`.set`/`.put` on a session-or-cache-named object. Allow-list: line-local presence of `user_id` / `userId` / `user-id` silences (compound key detected).

See the full threat catalog for every documented detection.

Further reading

  • MCP Security Best Practices — Session Hijacking
  • CWE-384: Session Fixation

Scan an MCP server for this issue

MCPSafe runs this check — and every other rule in the catalog — on any MCP server you paste in.

Scan now