FlawOpen

flawopen.com/AI Security/mcp-typescript-sdk-bearer-token-audience-validation

● CWE-863 · CVSS 6.8 · Média
Pesquisa · FlawOpen

SDK TypeScript do MCP aceitava tokens sem validar o público

A GHSA-rvq5-wwqv-78pq afeta servidores HTTP MCP que aceitam tokens sem conferir seu público. Atualize e habilite expectedResource, retornando o público verificado em AuthInfo.resource.[1]

💡 Explicação em Linguagem Simples (ELI5)

Um segurança aceita um crachá válido, mas não confere para qual prédio ele dá acesso. Se o mesmo emissor fornece crachás para vários prédios, um crachá de outro prédio pode ser aceito. O servidor MCP precisa comparar o destino do crachá com sua própria URL de recurso.[1]

Conceitos Centrais e Termos

Público (`aud`)
O recurso ou serviço para o qual um token de acesso foi emitido. Assinatura válida ou introspecção bem-sucedida não prova, por si só, que o token se destinava a este servidor MCP.[1], [7]
`expectedResource`
Opção habilitada explicitamente no middleware corrigido. Com ela, o URL de recurso configurado é comparado ao recurso informado pelo verificador do token; divergências recebem HTTP 401.[1], [2], [7]
`AuthInfo.resource`
URL do recurso derivada pelo verificador a partir de dados confiáveis de validação ou introspecção do token. O middleware corrigido precisa desse valor; se ele faltar, as requisições são rejeitadas quando a verificação está habilitada.[1], [2], [7]
Pacotes afetados
A GHSA abrange @modelcontextprotocol/sdk 1.6.0–1.31.0, @modelcontextprotocol/server 2.0.0–2.2.0, @modelcontextprotocol/express 2.0.0–2.0.1 e @modelcontextprotocol/server-legacy 2.0.0–2.3.0. Não há CVE; o fornecedor associa o problema à CWE-863.[1], [3], [6]

Mapeamentos de frameworks

  • Referência CWE para a fraqueza descrita neste guia: CWE-863

Fluxo de Ataque Passo a Paso

Passo 1

Um emissor atende várias APIs

A implantação afetada usa autenticação bearer HTTP para MCP, e o servidor de autorização emite tokens para mais de um serviço. Um token destinado a outra API ainda pode estar assinado corretamente e dentro da validade.[1]

Passo 2

O verificador valida o token, mas não o destino

Na integração afetada, requireBearerAuth() / verifyBearerToken() não tinham verificação interna de recurso esperado. Se verifyAccessToken() também não conferisse aud, um token de outro serviço poderia ser aceito.[1], [2], [5]

Passo 3

O token do serviço errado chega à autorização MCP

Um solicitante com token válido para outro serviço pode ser tratado como autenticado neste servidor MCP. A GHSA atribui CVSS 3.1 6,8 e CWE-863; não relata incidente específico em exploração.[1], [4]

Passo 4

Atualize e vincule a validação ao recurso MCP

Use a versão corrigida, configure expectedResource com o identificador deste servidor e faça verifyAccessToken() retornar o público verificado como AuthInfo.resource. A atualização não habilita a opção; sem resource, todas as requisições recebem 401.[1], [2], [5], [3], [6], [7]

Pacotes e versões afetadas do MCP TypeScript SDK

PacoteVersões afetadasVersão corrigida
@modelcontextprotocol/sdk1.6.0 a 1.31.01.32.0 ou posterior
@modelcontextprotocol/server2.0.0 a 2.2.02.3.0 ou posterior
@modelcontextprotocol/express2.0.0 a 2.0.12.0.2 ou posterior
@modelcontextprotocol/server-legacy2.0.0 a 2.3.02.3.1 ou posterior
Qualquer pacote com validação própria de aud em verifyAccessToken()O aplicativo pode já implementar a verificação que falta no helper.Confirme que a comparação é estrita e usa o identificador de recurso pretendido.

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

Este exemplo segue o formato documentado pelo SDK e a correção incorporada. verifyJwt representa o validador JWT ou chamada de introspecção já existente na aplicação. Antes da correção, o middleware não oferecia expectedResource nem comparava a audience; a versão corrigida compara o recurso configurado com AuthInfo.resource. Use o identificador exato que o servidor de autorização coloca em aud; o exemplo seleciona uma URL de audience na mesma origem e deixa o SDK comparar o recurso completo. Atualize o SDK 1.x para 1.32.0 ou posterior; no 2.x, use @modelcontextprotocol/server 2.3.0 ou posterior. Com Express, atualize também @modelcontextprotocol/express para 2.0.2 ou posterior. Como AuthInfo.resource é um URL, um valor aud simples que não seja URL não pode ser comparado por expectedResource: valide esse identificador rigorosamente em verifyAccessToken() e deixe expectedResource sem configuração nesse deployment. A implementação de verifyJwt é específica da aplicação e foi omitida; não há falsificação de token nem procedimento de exploração.[1], [2], [5], [3], [6], [7]

IMPLEMENTAÇÃO VULNERÁVEL
import { requireBearerAuth } from '@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js';

const mcpServerUrl = new URL('https://api.example.com/mcp');
const auth = requireBearerAuth({
  verifier: {
    async verifyAccessToken(token) {
      const payload = await verifyJwt(token); // A verificação JWT da aplicação
      return {
        token,
        clientId: payload.sub,
        scopes: payload.scopes,
        expiresAt: payload.exp,
        // O recurso não é retornado, e o helper afetado não tinha a opção expectedResource.
      };
    },
  },
});
PATCH SEGURO E ROBUSTO
import { requireBearerAuth } from '@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js';

const mcpServerUrl = new URL('https://api.example.com/mcp');
const auth = requireBearerAuth({
  verifier: {
    async verifyAccessToken(token) {
      const payload = await verifyJwt(token); // A verificação JWT da aplicação
      // aud pode ser uma string, uma lista ou estar ausente. Informe o recurso deste servidor.
      const audience = [payload.aud ?? []].flat().find(
        aud => URL.canParse(aud) && new URL(aud).origin === mcpServerUrl.origin,
      );
      const resource = audience ? new URL(audience) : undefined;
      return {
        token,
        clientId: payload.sub,
        scopes: payload.scopes,
        expiresAt: payload.exp,
        resource,
      };
    },
  },
  expectedResource: mcpServerUrl,
});

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

Fontes

← AI Security Directory →