1 Critical
2 High
0 Medium
0 Low
0 Info
3 Total
8.6 Max CVSS

Severity Distribution

OWASP MCP Top 10 Coverage

Framework Compliance

Auditor Breakdown

AuditorFindingsMax CVSSScore
auth 2 8.6 75/100
tools 1 6.8 90/100

Findings

MCP-AUTH-001 Protected Resource Metadata Missing CRITICAL CVSS 8.6 definitive
CWECWE-287 — Improper Authentication
Detectionendpoint
Efforthigh
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N

Evidence

GET https://mcp.exa.ai/.well-known/oauth-protected-resource — HTTP 404. Status: 404. Content-Type: text/plain; charset=utf-8.

Risk

Entry point of the entire MCP auth discovery chain is missing. MCP clients cannot determine authorization server location, cannot discover required scopes, and per the spec MUST fail the connection attempt. The server has no machine-readable auth mechanism.

Recommendation

Serve RFC 9728 compliant metadata at /.well-known/oauth-protected-resource with 'authorization_servers' array. Alternatively, include resource_metadata URI in WWW-Authenticate header on 401 responses. FastMCP serves this endpoint automatically when any auth provider is configured.

# FastMCP — automatic endpoint, just configure auth
from fastmcp import FastMCP
from fastmcp.server.auth import OAuthProvider

mcp = FastMCP(
    name='My Server',
    auth=OAuthProvider(...)
)
# /.well-known/oauth-protected-resource served automatically

Standards

  • MCP-SPEC-AUTH: Protected Resource Metadata Discovery Requirements
  • RFC9728: Protected Resource Metadata
  • OWASP-MCP07: MCP07 — Insufficient Authentication & Authorization
  • FMCP-TIER1: TokenVerifier — minimum auth tier
MCP-AUTH-006 Authorization Server Metadata Endpoint Missing HIGH CVSS 7.2 definitive
CWECWE-287 — Improper Authentication
Detectionendpoint
Efforthigh
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:H

Evidence

GET https://mcp.exa.ai/.well-known/oauth-authorization-server — failed or not valid JSON. GET https://mcp.exa.ai/.well-known/openid-configuration — failed or not valid JSON. Neither discovery endpoint returned valid Authorization Server Metadata.

Risk

MCP clients cannot verify PKCE support, discover token endpoint, or check DCR support. The spec requires clients to refuse authorization if neither discovery mechanism returns valid metadata.

Recommendation

Serve OAuth 2.0 Authorization Server Metadata at /.well-known/oauth-authorization-server (preferred) or OpenID Connect Discovery at /.well-known/openid-configuration. FastMCP OAuthProvider serves this automatically.

# FastMCP OAuthProvider serves AS metadata automatically
from fastmcp import FastMCP
from fastmcp.server.auth import OAuthProvider

mcp = FastMCP(
    name='My Server',
    auth=OAuthProvider(
        issuer='https://auth.example.com',
        # ... provider config
    )
)
# /.well-known/oauth-authorization-server served automatically

Standards

  • MCP-SPEC-AUTH: Authorization Server Metadata Discovery — MUST support RFC 8414 or OIDC
  • RFC8414: OAuth 2.0 Authorization Server Metadata
  • OWASP-MCP07: MCP07 — Insufficient Authentication & Authorization
MCP-TOOL-004 Tool Input Schema Missing Validation Constraints HIGH CVSS 6.8 definitive
CWECWE-20 — Improper Input Validation
Detectionintrospection
Effortlow
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N

Evidence

2 unconstrained sensitive parameter(s) across 2 tool(s): - web_search_exa.query (type: string, sensitivity: command/code, constraints: none) - get_code_context_exa.query (type: string, sensitivity: command/code, constraints: none)

Risk

Unconstrained string parameters for file paths, URLs, commands, or structured content are the entry point for injection attacks. Without maxLength, pattern, or enum constraints, LLM-generated inputs can contain path traversal sequences (../), shell metacharacters, or oversized payloads.

Recommendation

Add JSON Schema validation constraints to all sensitive parameters. Use 'maxLength' to prevent oversized inputs, 'pattern' for format enforcement, and 'enum' for known-value parameters.

from pydantic import Field

# BAD — unconstrained path parameter
@mcp.tool()
def read_file(path: str) -> str:  # ❌ no constraints
    ...

# GOOD — constrained with validation
@mcp.tool()
def read_file(
    path: str = Field(
        max_length=255,
        pattern=r'^[a-zA-Z0-9_/.-]+$',  # no ../ or special chars
        description='Relative file path within the workspace'
    )
) -> str:
    ...

Standards

  • OWASP-MCP05: MCP05 — Command Injection & Execution
  • MCP-SPEC-INPUT: Input Validation — tool input sanitization
  • OWASP-LLM02: LLM02 — Insecure Output Handling

Remediation Priorities

#FindingSeverityCVSSEffortAction
1 MCP-AUTH-001 critical 8.6 high Serve RFC 9728 compliant metadata at /.well-known/oauth-protected-resource with 'authorization_serve...
2 MCP-AUTH-006 high 7.2 high Serve OAuth 2.0 Authorization Server Metadata at /.well-known/oauth-authorization-server (preferred)...
3 MCP-TOOL-004 high 6.8 low Add JSON Schema validation constraints to all sensitive parameters. Use 'maxLength' to prevent overs...

Standards Cross-Reference

StandardFindings
FMCP-TIER1MCP-AUTH-001
MCP-SPEC-AUTHMCP-AUTH-001, MCP-AUTH-006
MCP-SPEC-INPUTMCP-TOOL-004
OWASP-LLM02MCP-TOOL-004
OWASP-MCP05MCP-TOOL-004
OWASP-MCP07MCP-AUTH-001, MCP-AUTH-006
RFC8414MCP-AUTH-006
RFC9728MCP-AUTH-001