Fallo en el SDK oficial de MCP en Python expone credenciales OAuth
Un servidor MCP hostil podía desviar el flujo OAuth del cliente y quedarse con su client secret y su clave PKCE. Hay arreglo en 1.30.0 y 2.2.0, pero dos proveedores exigen un cambio extra.

El SDK oficial de Python para el Model Context Protocol (MCP) ha corregido un fallo que permitía a un servidor malicioso quedarse con las credenciales OAuth con las que un cliente se autentica contra un servicio real. Afecta a las versiones 1.9.1 a 1.29.1 de la rama 1.x y a las 2.0.0 a 2.1.1 de la 2.x, y está arreglado en la 1.30.0 y la 2.2.0. A 29 de septiembre no había CVE asignado.
El detalle está en el aviso de seguridad de los mantenedores, publicado el 28 de septiembre, el mismo día en que Cycode, la empresa que reportó el fallo, sacó su análisis. Las comprobaciones, en cambio, viajaron en las notas de la versión 1.30.0 del 7 de septiembre, listadas como cambio de comportamiento y no como corrección de seguridad.
Cómo se roba la credencial
Cuando un cliente MCP necesita iniciar sesión, pregunta al servidor al que se conecta dónde está su servidor de autorización. En las versiones afectadas el SDK no siempre verificaba esa respuesta. Un servidor hostil podía apuntar al servicio de login que le conviniera, y el cliente le enviaba el client secret, el código de autorización y la clave de prueba PKCE. Con ese material, el atacante pide un token de acceso válido al servicio legítimo. Cycode completó el intercambio en una prueba y sostiene que el token resultante hereda los permisos que tuviera la aplicación. El client secret es de vida larga: sigue funcionando hasta que alguien lo cambie.
La prueba PKCE existe justamente para que un código de autorización robado no se pueda reutilizar, así que entregarla anula también esa defensa. En el proveedor interactivo hace falta que una persona apruebe el inicio de sesión, pero la página que ve es la auténtica y no hay nada raro a la vista. Los dos proveedores máquina a máquina no necesitan a nadie. El fallo puntúa 7,5 para esos dos y 6,5 para el interactivo.
Está afectada cualquier aplicación que use el SDK como cliente MCP sobre HTTP con OAuthClientProvider, ClientCredentialsOAuthProvider, PrivateKeyJWTOAuthProvider o el deprecado RFC7523OAuthClientProvider, y que pueda conectarse a un servidor que no controle del todo mientras guarda credenciales de un servicio real. Los servidores MCP construidos con el SDK, los clientes locales por stdio y los que aportan sus propios tokens quedan fuera.
Qué hacer
Actualizar a 1.30.0 o 2.2.0 no cierra el asunto en dos casos. Con ClientCredentialsOAuthProvider y PrivateKeyJWTOAuthProvider hay que pasar además issuer= para nombrar el servicio de login al que pertenecen esas credenciales; sin eso, siguen haciendo caso al servidor. En la 1.30.0 el aviso es un DeprecationWarning corriente, y Python los oculta por defecto, así que es fácil no enterarse. El RFC7523OAuthClientProvider deprecado no tiene parámetro issuer=, de modo que toca migrar a otro. Después de actualizar conviene limpiar una vez los registros de cliente OAuth guardados, porque los antiguos no están atados a ningún emisor. Y si el cliente pudo haber hablado con un servidor no confiable, hay que rotar el client secret y revocar los tokens en el servicio de login.
Ni el aviso ni Cycode reportan ataques que hayan explotado esto, y no consta ninguno en otro sitio. En las versiones antiguas no hay más remedio que conectarse solo a servidores MCP de confianza.


