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

OAuth Token Request Missing Resource Indicator

HIGHCWE: CWE-345Rule: MCP-279

MCP clients that request OAuth tokens without a `resource` parameter violate RFC 8707 and the MCP Authorization Specification, allowing tokens issued for one MCP server to be replayed against any other server the authorization server can mint tokens for.

What it is

This is an insufficient-verification-of-data-authenticity defect (CWE-345). RFC 8707 (Resource Indicators for OAuth 2.0) defines the `resource` parameter as the mechanism that binds a token's audience to a specific resource server. Without it, the authorization server has no way to scope the issued access token, and a token meant for `https://mcp-a.example.com` can be presented to `https://mcp-b.example.com` if both share the same authorization server — the classic confused-deputy attack against multi-tenant resource ecosystems.

Why it matters for MCP

The MCP Authorization Specification (2025-11-25) makes `resource` mandatory on every token request precisely because MCP servers are designed to live behind shared authorization servers. A user might authenticate once with their Anthropic account and have access tokens minted for many distinct MCP servers; resource indicators are what stop one server (or a compromise of one server) from being able to replay tokens against the others. Because MCP server endpoints are increasingly published in public registries, the cost of forgetting the parameter is concrete: one compromised server becomes a credential-replay platform against every sibling server.

Vulnerable example

example.py
1
from fastmcp import FastMCP
2
3
mcp = FastMCP("my-mcp")
4
5
@mcp.tool()
6
def list_files() -> list[str]:
7
    return []
8
9
def get_token(oauth_session, code):
10
    # VULNERABLE: no `resource` kwarg — token can be replayed against any
11
    # other MCP server backed by the same authorization server.
12
    return oauth_session.fetch_token(
13
        grant_type="authorization_code",
14
        code=code,
15
    )

Secure example

example.py
1
from fastmcp import FastMCP
2
3
mcp = FastMCP("my-mcp")
4
5
@mcp.tool()
6
def list_files() -> list[str]:
7
    return []
8
9
def get_token(oauth_session, code):
10
    return oauth_session.fetch_token(
11
        grant_type="authorization_code",
12
        code=code,
13
        resource="https://my-mcp.example.com",
14
    )

How MCPSafe detects this

MCPSafe fires per-occurrence on a token-fetch call (`fetch_token`, `requests.post(...token_endpoint...)`, `oauth2Client.getToken`, `OAuth2Session.fetch_token`, etc.) when the same line contains no `resource=`, `resource:`, or `"resource":` token. Detection is gated to MCP-context files. The v1 detection is single-line: if the request body is built up across multiple statements (`params = {}; params["resource"] = ...; oauth.fetch_token(**params)`), the rule does not unwind the dataflow — keep the kwarg inline at the call site or accept the false positive and silence with `# nosem` after manual review.

See the full threat catalog for every documented detection.

Further reading

  • MCP Authorization Specification (2025-11-25)
  • RFC 8707 — Resource Indicators for OAuth 2.0
  • CWE-345: Insufficient Verification of Data Authenticity

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