FlawOpen

flawopen.com/AI Security/mcp-python-sdk-oauth-issuer-confusion

● CWE-345 / CWE-522 · CVSS 7.5[1] · Alta
Investigación · FlawOpen

Fallo de validación del emisor OAuth en MCP Python SDK

GHSA-qx49-fqc8-xw99 permitía que un servidor MCP HTTP influyera en el destino al que los clientes OAuth afectados del SDK de Python podían enviar credenciales. Actualice a mcp 1.30.0 o 2.2.0; los proveedores máquina a máquina deben definir issuer=. No hay CVE asignado.[1], [3], [8]

Vector CVSSCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N[1]
💡 Explicación en Lenguaje Sencillo (ELI5)

Una empresa envía una llave sellada al banco cuya dirección figura en una tarjeta de directorio aprobada. El servidor MCP podía proporcionar la tarjeta y una ruta alternativa no comprobaba que la entrada perteneciera al banco esperado. La validación del emisor compara la identidad de la tarjeta con el banco configurado como confiable antes de enviar la llave.[1], [2]

Conceptos Clave y Términos

Cliente MCP
Aplicación que usa Model Context Protocol para conectarse a herramientas o datos de un servidor MCP. Este fallo afecta al SDK de Python cuando se usa como cliente HTTP con sus proveedores OAuth.[1]
Emisor del servidor de autorización
Identificador estable del servicio OAuth que emite tokens. El cliente debe comparar los metadatos descubiertos con un emisor que espere de forma independiente.[1], [2]
Protected Resource Metadata (PRM)
Metadatos que pueden identificar servidores de autorización para un recurso protegido. El SDK también dispone de una ruta heredada cuando falta PRM.[1], [2]
Verificador PKCE
Secreto generado por el cliente para vincular el intercambio del código OAuth con el cliente que inició el flujo. No debe divulgarse a un endpoint no confiable.[1], [2]
CWE-345 / CWE-522
Verificación insuficiente de la autenticidad de los datos: aceptar datos sin comprobar adecuadamente que proceden de la fuente esperada. CWE-522 describe la protección insuficiente de credenciales.[1], [4], [7]

Mapeos de marcos

  • Referencia CWE para la debilidad descrita en esta guía: CWE-345 CWE-522

Flujo de Ataque Paso a Paso

Paso 1

Un cliente HTTP MCP conserva credenciales OAuth

La aplicación usa una versión afectada de mcp y uno de los proveedores OAuth del SDK. Puede conectarse a un servidor MCP no plenamente confiable mientras conserva un secreto de cliente, una clave de firma o un registro de cliente almacenado.[1]

Paso 2

El servidor influye en el descubrimiento de autorización

mcp 1.9.1–1.29.1 no validaba el emisor ni vinculaba credenciales en todas las rutas de descubrimiento. mcp 2.0.0–2.1.1 estaba afectado cuando faltaba PRM y se usaba la alternativa heredada, o durante el descubrimiento tras 403 insufficient_scope. En ambas ramas, los proveedores máquina a máquina carecían de issuer= para vincular credenciales preconfiguradas. El intervalo del paquete indicado por el aviso empieza en la versión preliminar 2.0.0a1 y es <2.2.0; por tanto, las versiones preliminares afectadas de 2.0.0 también están incluidas.[1], [3], [8]

Paso 3

El endpoint de tokens recibe credenciales

El cliente puede enviar un secreto de cliente, un código de autorización y el verificador PKCE, o una aserción firmada, a un endpoint elegido mediante esos metadatos. La credencial depende del proveedor; no significa que todos los clientes estén afectados.[1], [2]

Paso 4

El impacto depende del proveedor y los permisos

Quien recibe las credenciales o los tokens puede usarlos dentro del ámbito autorizado. El aviso puntúa con CVSS 7,5 a los proveedores desatendidos; el proveedor interactivo recibe 6,5 porque una persona debe iniciar el inicio de sesión. El aviso indica que no se ha asignado ningún CVE.[1]

Paso 5

Fijar el emisor cierra la brecha de confianza

Las versiones corregidas determinan el emisor esperado antes del descubrimiento, rechazan metadatos incompatibles y vinculan los registros almacenados a ese emisor. Los proveedores máquina a máquina también requieren un issuer= explícito.[1], [2], [3], [8]

Matriz de versiones y acciones de OAuth en MCP Python SDK

Configuración del clienteCondición afectada documentadaAcción requerida
Cliente HTTP OAuth con mcp 1.9.1–1.29.1Todas las rutas de descubrimiento carecían de validación del emisor y de una vinculación uniforme entre credenciales y emisor.Actualice a mcp 1.30.0 o posterior y compruebe la versión desplegada.
Cliente HTTP OAuth con mcp 2.0.0–2.1.1Afectado si falta PRM y se usa la alternativa heredada, o durante el descubrimiento de escalado 403 insufficient_scope. El intervalo del paquete indicado por el aviso empieza en la versión preliminar 2.0.0a1 y es <2.2.0; por tanto, las versiones preliminares afectadas de 2.0.0 también están incluidas.Actualice a mcp 2.2.0 o posterior y compruebe la versión desplegada.
ClientCredentialsOAuthProvider o PrivateKeyJWTOAuthProvider con credenciales preconfiguradasLas versiones afectadas no ofrecían issuer= para vincular estas credenciales con el servidor de autorización previsto.Tras actualizar, establezca issuer= explícitamente. Migre desde RFC7523OAuthClientProvider, obsoleto en la rama 1.x.
Servidor creado con el SDK, cliente stdio o cliente que aporta su propio token/cabeceraNo está afectado por este aviso.No requiere acciones para este fallo concreto; vuelva a evaluar si la aplicación también usa un cliente HTTP OAuth afectado.

Análisis de Causa Raíz

El fallo de confianza tenía dos partes relacionadas: algunas rutas de descubrimiento afectadas no comparaban de forma coherente el issuer de los metadatos del servidor de autorización con un emisor esperado de manera independiente del servidor MCP, y las credenciales almacenadas o aprovisionadas previamente no quedaban vinculadas a su emisor previsto. Por ello, un servidor MCP malicioso o comprometido podía dirigir el intercambio de tokens a un endpoint bajo su control y recibir material OAuth del cliente. Las correcciones determinan el emisor esperado antes del descubrimiento, rechazan las discrepancias y vinculan los registros almacenados a ese emisor; los proveedores máquina a máquina sin interacción también requieren un issuer= explícito.[1], [2]

Código Fuente: Vulnerable vs. Seguro

El argumento issuer está disponible en las versiones corregidas del SDK. Vincula las credenciales máquina a máquina con su servidor de autorización; no sustituye la actualización, la eliminación de registros antiguos sin vínculo ni la rotación de credenciales que podrían haberse expuesto.[2], [3], [8]

Fragmento de origen: mcp.client.auth

IMPLEMENTACIÓN VULNERABLE
import os
from mcp.client.auth import ClientCredentialsOAuthProvider

auth = ClientCredentialsOAuthProvider(
    client_id=os.environ["MCP_CLIENT_ID"],
    client_secret=os.environ["MCP_CLIENT_SECRET"],
)
PARCHE SEGURO Y ROBUSTO
import os
from mcp.client.auth import ClientCredentialsOAuthProvider

auth = ClientCredentialsOAuthProvider(
    client_id=os.environ["MCP_CLIENT_ID"],
    client_secret=os.environ["MCP_CLIENT_SECRET"],
    issuer=os.environ["MCP_AUTH_ISSUER"],
)
# Use mcp >= 1.30.0 (1.x) o >= 2.2.0 (2.x).

Lista de Verificación de Seguridad para Ingeniería

Fuentes

← AI Security Directory →