FlawOpen

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

● CWE-345 / CWE-522 · CVSS 7.5[1] · Alta
Pesquisa · FlawOpen

Falha de validação de issuer OAuth no MCP Python SDK

A GHSA-qx49-fqc8-xw99 permitia que um servidor MCP HTTP influenciasse para onde clientes OAuth afetados do SDK Python poderiam enviar credenciais. Atualize para mcp 1.30.0 ou 2.2.0; provedores máquina a máquina precisam definir issuer=. Não há CVE atribuído.[1], [3], [8]

Vetor CVSSCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N[1]
💡 Explicação em Linguagem Simples (ELI5)

Uma empresa envia uma chave lacrada ao banco cujo endereço aparece em um cartão de diretório aprovado. O servidor MCP podia fornecer o cartão, e um caminho alternativo não verificava se a entrada pertencia ao banco esperado. A validação do emissor compara a identidade do cartão com o banco configurado como confiável antes de enviar a chave.[1], [2]

Conceitos Centrais e Termos

Cliente MCP
Aplicação que usa o Model Context Protocol para acessar ferramentas ou dados de um servidor MCP. Esta falha afeta o SDK Python usado como cliente HTTP com seus provedores OAuth.[1]
Emissor do servidor de autorização
Identificador estável do serviço OAuth que emite tokens. O cliente deve comparar os metadados descobertos com um emissor esperado de forma independente.[1], [2]
Protected Resource Metadata (PRM)
Metadados que podem identificar os servidores de autorização de um recurso protegido. O SDK também possui um caminho legado quando PRM não está disponível.[1], [2]
Verificador PKCE
Segredo gerado pelo cliente para vincular a troca do código OAuth ao cliente que iniciou o fluxo. Ele não deve ser enviado a um endpoint não confiável.[1], [2]
CWE-345 / CWE-522
Verificação insuficiente da autenticidade dos dados: aceitar dados sem confirmar adequadamente que vieram da origem esperada. A CWE-522 descreve a proteção insuficiente de credenciais.[1], [4], [7]

Mapeamentos de frameworks

Fluxo de Ataque Passo a Paso

Passo 1

Um cliente HTTP MCP mantém credenciais OAuth

A aplicação usa uma versão afetada de mcp e um dos provedores OAuth do SDK. Ela pode conectar-se a um servidor MCP não totalmente confiável enquanto mantém um segredo de cliente, uma chave de assinatura ou um cadastro de cliente armazenado.[1]

Passo 2

O servidor influencia a descoberta da autorização

mcp 1.9.1–1.29.1 não validava o issuer nem vinculava credenciais em todos os caminhos de descoberta. mcp 2.0.0–2.1.1 era afetado quando faltava PRM e ocorria o fallback legado, ou durante a descoberta após 403 insufficient_scope. Nas duas linhas, provedores máquina a máquina não tinham issuer= para vincular credenciais pré-provisionadas. O intervalo do pacote no aviso começa na versão de pré-lançamento 2.0.0a1 e é <2.2.0; portanto, os pré-lançamentos afetados de 2.0.0 também estão no escopo.[1], [3], [8]

Passo 3

O endpoint de token recebe credenciais

O cliente pode enviar um segredo de cliente, código de autorização e verificador PKCE, ou uma asserção assinada, a um endpoint escolhido por esses metadados. A credencial depende do provedor; isso é uma falha de exposição de credenciais, não uma afirmação de que todo cliente é afetado.[1], [2]

Passo 4

O impacto depende do provedor e das permissões

Quem recebe as credenciais ou tokens pode usá-los dentro do escopo autorizado. O aviso atribui CVSS 7,5 aos provedores sem interação; o provedor interativo recebe 6,5 porque uma pessoa precisa iniciar o login. O aviso informa que nenhum CVE foi atribuído.[1]

Passo 5

Fixar o emissor fecha a lacuna de confiança

As versões corrigidas determinam o emissor esperado antes da descoberta, rejeitam metadados incompatíveis e vinculam cadastros armazenados a esse emissor. Provedores máquina a máquina também precisam de issuer= explícito.[1], [2], [3], [8]

Matriz de versões e ações do OAuth no MCP Python SDK

Configuração do clienteCondição afetada documentadaAção necessária
Cliente HTTP OAuth com mcp 1.9.1–1.29.1Todos os caminhos de descoberta não validavam o issuer nem vinculavam as credenciais de forma consistente.Atualize para mcp 1.30.0 ou posterior e confirme a versão implantada.
Cliente HTTP OAuth com mcp 2.0.0–2.1.1Afetado quando falta PRM e ocorre o fallback legado, ou durante a descoberta de escalonamento 403 insufficient_scope. O intervalo do pacote no aviso começa na versão de pré-lançamento 2.0.0a1 e é <2.2.0; portanto, os pré-lançamentos afetados de 2.0.0 também estão no escopo.Atualize para mcp 2.2.0 ou posterior e confirme a versão implantada.
ClientCredentialsOAuthProvider ou PrivateKeyJWTOAuthProvider com credenciais provisionadasAs versões afetadas não ofereciam issuer= para vincular essas credenciais ao servidor de autorização esperado.Após atualizar, defina issuer= explicitamente. Migre do RFC7523OAuthClientProvider obsoleto na linha 1.x.
Servidor criado pelo SDK, cliente stdio ou cliente que fornece seu próprio token/cabeçalhoNão afetado por este aviso.Nenhuma ação para esta falha específica; reavalie se o aplicativo também usa um cliente HTTP OAuth afetado.

Análise de Causa Raiz

A falha de confiança tinha duas partes relacionadas: os caminhos de descoberta afetados nem sempre comparavam o issuer dos metadados do servidor de autorização com um valor esperado independentemente do servidor MCP, e as credenciais armazenadas ou pré-provisionadas não eram vinculadas ao emissor correto. Assim, um servidor MCP malicioso ou comprometido podia direcionar a troca de token para um endpoint sob seu controle e receber material OAuth mantido pelo cliente. As correções determinam o emissor esperado antes da descoberta, rejeitam divergências e vinculam os registros armazenados a esse emissor; provedores máquina a máquina sem interação também exigem issuer= explícito.[1], [2]

Código-Fonte: Vulnerável vs. Seguro

O argumento issuer existe nas versões corrigidas do SDK. Ele vincula credenciais máquina a máquina ao servidor de autorização correto; não substitui a atualização, a limpeza de cadastros antigos sem vínculo ou a rotação de credenciais possivelmente expostas.[2], [3], [8]

Trecho de origem: mcp.client.auth

IMPLEMENTAÇÃO VULNERÁVEL
import os
from mcp.client.auth import ClientCredentialsOAuthProvider

auth = ClientCredentialsOAuthProvider(
    client_id=os.environ["MCP_CLIENT_ID"],
    client_secret=os.environ["MCP_CLIENT_SECRET"],
)
PATCH SEGURO E 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 a versão mcp >= 1.30.0 (1.x) ou >= 2.2.0 (2.x).

Lista de Verificação de Segurança para Engenharia

Fontes

← AI Security Directory →