flawopen.com/AI Security/mcp-typescript-sdk-bearer-token-audience-validation
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]
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]
Framework-Zuordnungen
- CWE-Referenz für die in diesem Leitfaden beschriebene Schwachstelle: CWE-863
Schritt-für-Schritt Angriffsablauf
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]
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]
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
| Paket | Betroffene Versionen | Korrigierte Version |
|---|---|---|
@modelcontextprotocol/sdk | 1.6.0 bis 1.31.0 | 1.32.0 oder neuer |
@modelcontextprotocol/server | 2.0.0 bis 2.2.0 | 2.3.0 oder neuer |
@modelcontextprotocol/express | 2.0.0 bis 2.0.1 | 2.0.2 oder neuer |
@modelcontextprotocol/server-legacy | 2.0.0 bis 2.3.0 | 2.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]
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.
};
},
},
});
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
- ✓Ermitteln Sie MCP-HTTP-Server mit
requireBearerAuth()oderverifyBearerToken()und prüfen Sie, ob ihr Aussteller Tokens für mehrere APIs ausstellt.[1] - ✓Aktualisieren Sie SDK 1.x auf 1.32.0 oder neuer; für 2.x
@modelcontextprotocol/serverauf 2.3.0 oder neuer und mit Express@modelcontextprotocol/expressauf 2.0.2 oder neuer;server-legacyauf 2.3.1 oder neuer.[1], [3], [6] - ✓Setzen Sie
expectedResourcein vertrauenswürdiger Konfiguration auf die exakte Kennung dieses MCP-Servers; leiten Sie den Wert nicht aus der eingehenden Anfrage ab.[1], [2], [7] - ✓Lassen Sie
verifyAccessToken()das Token beim vertrauenswürdigen Autorisierungsserver prüfen und die verifizierte Audience alsAuthInfo.resourcezurückgeben. Verwendet der Aussteller eine einfache Audience-Kennung ohne URL, prüfen Sie sie strikt im Verifier und lassen SieexpectedResourceungesetzt; raten Sie den Wert nicht und wandeln Sie ihn nicht in eine URL um.[1], [2], [7] - ✓Testen Sie: Ein Token für diese Ressource funktioniert; Tokens für andere Dienste, fehlende Audience sowie abweichendes Schema, Host, Port oder Pfad führen zu 401.[1], [2], [7]
- ✓Ein Update genügt nicht:
expectedResourcebleibt ohne Konfiguration deaktiviert; fehltAuthInfo.resource, werden alle Anfragen abgewiesen.[1] - ✓Überwachen Sie Zugriffsprotokolle und Validierungstelemetrie auf unerwartete Audiences; widerrufen oder rotieren Sie Zugangsdaten nur, wenn Hinweise auf einen möglichen Missbrauch vorliegen.[1]
Quellen
- GitHub-Sicherheitshinweis GHSA-rvq5-wwqv-78pq
- MCP TypeScript SDK Pull Request #2930: expectedResource für requireBearerAuth
- MCP TypeScript SDK Versionshinweise 1.32.0
- MITRE CWE-863: Fehlerhafte Autorisierung
- MCP TypeScript SDK v2 pull request #2929: add expectedResource to bearer-token check
- MCP TypeScript SDK release notes for 2.3.0
- MCP TypeScript SDK server guide: bearer-token audience validation