FlawOpen

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

● CWE-863 · CVSS 6.8 · Mittel
Sicherheitsforschung · FlawOpen

MCP TypeScript SDK prüfte die Audience von Bearer-Tokens nicht

GHSA-rvq5-wwqv-78pq betrifft MCP-HTTP-Server, die Tokens ohne Audience-Prüfung akzeptierten. Aktualisieren, expectedResource aktivieren und die verifizierte Audience als AuthInfo.resource zurückgeben.[1]

💡 Einfache Erklärung (ELI5)

Ein Werkschutz akzeptiert einen gültigen Ausweis, prüft aber nicht, für welches Gebäude er gilt. Stellt dieselbe Stelle Ausweise für mehrere Gebäude aus, kann ein Ausweis für das Nachbargebäude durchgehen. Der MCP-Server muss das Ziel des Ausweises mit seiner eigenen Ressourcen-URL abgleichen.[1]

Kernkonzepte & Begriffe

Audience (`aud`)
Die Ressource oder der Dienst, für den ein Zugriffstoken ausgestellt wurde. Eine gültige Signatur oder erfolgreiche Introspektion beweist nicht, dass das Token für diesen MCP-Server bestimmt ist.[1], [7]
`expectedResource`
Eine aktiv zu setzende Option der korrigierten Middleware. Sie vergleicht die konfigurierte Ressourcen-URL mit der vom Tokenprüfer gemeldeten Ressource und weist Abweichungen mit HTTP 401 zurück.[1], [2], [7]
`AuthInfo.resource`
Ressourcen-URL, die der Prüfer aus vertrauenswürdigen Token-Validierungs- oder Introspektionsdaten ableitet. Die korrigierte Middleware benötigt diesen Wert; fehlt er, werden Anfragen bei aktivierter Prüfung abgewiesen.[1], [2], [7]
Betroffene Pakete
Die Meldung umfasst @modelcontextprotocol/sdk 1.6.0–1.31.0, @modelcontextprotocol/server 2.0.0–2.2.0, @modelcontextprotocol/express 2.0.0–2.0.1 und @modelcontextprotocol/server-legacy 2.0.0–2.3.0. Es gibt keine CVE; der Anbieter ordnet den Fehler CWE-863 zu.[1], [3], [6]

Framework-Zuordnungen

  • CWE-Referenz für die in diesem Leitfaden beschriebene Schwachstelle: CWE-863

Schritt-für-Schritt Angriffsablauf

Schritt 1

Ein Aussteller versorgt mehrere APIs

Die betroffene Bereitstellung nutzt MCP-HTTP-Bearer-Authentifizierung, und der Autorisierungsserver stellt Tokens für mehrere Dienste aus. Ein Token für eine andere API kann trotzdem korrekt signiert und noch gültig sein.[1]

Schritt 2

Das Token wird geprüft, sein Ziel aber nicht

In der betroffenen Integration enthielten requireBearerAuth() / verifyBearerToken() keine eingebaute Prüfung der erwarteten Ressource. Prüfte auch verifyAccessToken() aud nicht, konnte der MCP-Server ein Token für einen anderen Dienst akzeptieren.[1], [2], [5]

Schritt 3

Das Token des falschen Dienstes erreicht die MCP-Autorisierung

Ein Aufrufer mit einem gültigen Token für einen anderen Dienst kann bei diesem MCP-Server als authentifiziert gelten. Die Meldung nennt CVSS 3.1 6,8 und CWE-863; einen konkreten Angriff in freier Wildbahn beschreibt sie nicht.[1], [4]

Schritt 4

Aktualisieren und an diese MCP-Ressource binden

Verwenden Sie die korrigierte Version, setzen Sie expectedResource auf die Kennung dieses Servers und geben Sie die verifizierte Audience aus verifyAccessToken() als AuthInfo.resource zurück. Das Update aktiviert die Option nicht; ohne resource erhalten alle Anfragen 401.[1], [2], [5], [3], [6], [7]

Betroffene MCP-TypeScript-SDK-Pakete

PaketBetroffene VersionenKorrigierte Version
@modelcontextprotocol/sdk1.6.0 bis 1.31.01.32.0 oder neuer
@modelcontextprotocol/server2.0.0 bis 2.2.02.3.0 oder neuer
@modelcontextprotocol/express2.0.0 bis 2.0.12.0.2 oder neuer
@modelcontextprotocol/server-legacy2.0.0 bis 2.3.02.3.1 oder neuer
Jedes Paket mit eigener aud-Prüfung in verifyAccessToken()Die Anwendung setzt die fehlende Helper-Prüfung möglicherweise bereits um.Prüfen Sie, ob der Vergleich strikt ist und die vorgesehene Ressourcen-ID verwendet.

Quellcode: Verwundbar vs. Sicher

Das Beispiel folgt der dokumentierten SDK-Form und der übernommenen Korrektur. verifyJwt steht für den bereits vorhandenen JWT-Prüfer oder Introspektionsaufruf der Anwendung. Vor der Korrektur bot die Middleware weder expectedResource noch einen Audience-Abgleich; die korrigierte Version vergleicht die konfigurierte Ressource mit AuthInfo.resource. Verwenden Sie genau die Kennung, die der Autorisierungsserver in aud einträgt; das Beispiel wählt eine Audience-URL desselben Ursprungs aus und überlässt den vollständigen Ressourcenvergleich dem SDK. Aktualisieren Sie SDK 1.x auf 1.32.0 oder neuer; für 2.x verwenden Sie @modelcontextprotocol/server 2.3.0 oder neuer. Mit Express muss auch @modelcontextprotocol/express auf 2.0.2 oder neuer aktualisiert werden. Da AuthInfo.resource eine URL ist, lässt sich ein einfacher aud-Wert ohne URL nicht mit expectedResource vergleichen: Prüfen Sie diese Kennung strikt in verifyAccessToken() und lassen Sie expectedResource für diese Bereitstellung ungesetzt. Die anwendungsspezifische Implementierung von verifyJwt ist ausgelassen; Tokenfälschung oder Exploit-Ablauf werden nicht gezeigt.[1], [2], [5], [3], [6], [7]

VERWUNDBARE IMPLEMENTIERUNG
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); // JWT-Prüfung der Anwendung
      return {
        token,
        clientId: payload.sub,
        scopes: payload.scopes,
        expiresAt: payload.exp,
        // Es wird keine Ressource zurückgegeben, und dem betroffenen Helper fehlte die Option expectedResource.
      };
    },
  },
});
GEHÄRTETER SICHERHEITS-PATCH
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); // JWT-Prüfung der Anwendung
      // aud kann eine Zeichenkette, eine Liste oder nicht vorhanden sein. Gib den Eintrag für diesen Server zurück.
      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,
});

Checkliste für Engineering & Systemsicherheit

Quellen

← AI Security Directory →