flawopen.com/AI Security/mcp-typescript-sdk-bearer-token-audience-validation
SDK TypeScript MCP tidak memeriksa audience token Bearer
GHSA-rvq5-wwqv-78pq berdampak pada server HTTP MCP yang menerima token tanpa memeriksa audience. Perbarui, aktifkan expectedResource, dan kembalikan audience terverifikasi melalui AuthInfo.resource.[1]
Petugas keamanan menerima kartu akses yang valid, tetapi tidak memeriksa gedung mana yang dibuka kartu itu. Jika satu penerbit membuat kartu untuk banyak gedung, kartu gedung sebelah bisa ikut diterima. Server MCP harus mencocokkan tujuan kartu dengan URL resource miliknya.[1]
Konsep Kunci & Istilah
Audience (`aud`)- Resource atau layanan yang menjadi tujuan token akses. Tanda tangan valid atau introspeksi berhasil tidak membuktikan bahwa token tersebut ditujukan kepada server MCP ini.[1], [7]
`expectedResource`- Pengaturan yang harus diaktifkan secara eksplisit pada middleware yang telah diperbaiki. Nilai ini membandingkan URL resource konfigurasi dengan resource yang dilaporkan verifier token; ketidakcocokan menghasilkan HTTP 401.[1], [2], [7]
Pemetaan kerangka kerja
- Referensi CWE untuk kelemahan yang dijelaskan dalam panduan ini: CWE-863
Alur Serangan Langkah demi Langkah
Satu penerbit melayani beberapa API
Penerapan terdampak menggunakan autentikasi Bearer HTTP MCP dan server otorisasinya menerbitkan token untuk beberapa layanan. Token untuk API lain masih dapat memiliki tanda tangan yang benar dan belum kedaluwarsa.[1]
Perbarui dan ikat pemeriksaan ke resource MCP
Gunakan rilis yang sudah diperbaiki, atur expectedResource ke pengenal resource server ini, dan minta verifyAccessToken() mengembalikan audience terverifikasi sebagai AuthInfo.resource. Pembaruan saja tidak mengaktifkan opsi ini; tanpa resource, semua permintaan mendapat 401.[1], [2], [5], [3], [6], [7]
Paket MCP TypeScript SDK yang terdampak
| Paket | Versi terdampak | Versi perbaikan |
|---|---|---|
@modelcontextprotocol/sdk | 1.6.0–1.31.0 | 1.32.0 atau lebih baru |
@modelcontextprotocol/server | 2.0.0–2.2.0 | 2.3.0 atau lebih baru |
@modelcontextprotocol/express | 2.0.0–2.0.1 | 2.0.2 atau lebih baru |
@modelcontextprotocol/server-legacy | 2.0.0–2.3.0 | 2.3.1 atau lebih baru |
Paket apa pun yang memvalidasi aud sendiri di verifyAccessToken() | Aplikasi mungkin sudah menerapkan pemeriksaan yang tidak ada di helper. | Pastikan perbandingannya ketat dan memakai pengenal resource yang dimaksud. |
Kode Sumber: Rentan vs Aman
Contoh ini mengikuti bentuk yang didokumentasikan SDK dan perbaikan yang telah digabungkan. verifyJwt mewakili validator JWT atau panggilan introspeksi yang sudah dimiliki aplikasi. Sebelum perbaikan, middleware tidak menyediakan expectedResource dan tidak membandingkan audience; versi yang diperbaiki mencocokkan resource konfigurasi dengan AuthInfo.resource. Gunakan pengenal persis yang ditempatkan server otorisasi di aud; contoh memilih URL audience dari origin yang sama lalu membiarkan SDK membandingkan resource lengkap. Perbarui SDK 1.x ke 1.32.0 atau lebih baru; untuk 2.x gunakan @modelcontextprotocol/server 2.3.0 atau lebih baru. Pengguna Express juga harus memperbarui @modelcontextprotocol/express ke 2.0.2 atau lebih baru. Karena AuthInfo.resource bertipe URL, nilai aud biasa yang bukan URL tidak dapat dibandingkan melalui expectedResource: validasi pengenal itu secara ketat di dalam verifyAccessToken() dan biarkan expectedResource tidak disetel untuk deployment tersebut. Implementasi verifyJwt khusus aplikasi dan sengaja tidak disertakan; tidak ada pemalsuan token atau langkah eksploitasi.[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); // Verifikasi JWT aplikasi
return {
token,
clientId: payload.sub,
scopes: payload.scopes,
expiresAt: payload.exp,
// Resource tidak dikembalikan, dan helper yang terdampak tidak memiliki opsi 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); // Verifikasi JWT aplikasi
// aud dapat berupa string, daftar, atau tidak ada. Kembalikan entri untuk server ini.
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,
});
Daftar Periksa Penguatan Sistem Rekayasa
- ✓Inventarisasi server HTTP MCP yang memakai
requireBearerAuth()atauverifyBearerToken()dan pastikan apakah penerbit otorisasi memberikan token untuk beberapa API.[1] - ✓Perbarui SDK 1.x ke 1.32.0 atau lebih baru; untuk 2.x gunakan
@modelcontextprotocol/server2.3.0 atau lebih baru dan, untuk Express,@modelcontextprotocol/express2.0.2 atau lebih baru; perbaruiserver-legacyke 2.3.1 atau lebih baru.[1], [3], [6] - ✓Atur
expectedResourceke pengenal persis server MCP ini dalam konfigurasi server tepercaya; jangan menurunkannya dari permintaan masuk.[1], [2], [7] - ✓Pastikan
verifyAccessToken()memvalidasi token melalui server otorisasi tepercaya dan mengembalikan audience terverifikasi melaluiAuthInfo.resource. Jika penerbit memakai pengenal audience biasa yang bukan URL, validasi secara ketat di dalam verifier dan jangan setelexpectedResource; jangan menebak atau mengubahnya menjadi URL.[1], [2], [7] - ✓Uji bahwa token untuk resource ini berhasil, sedangkan token layanan lain, audience yang hilang, dan audience dengan scheme, host, port, atau path berbeda menghasilkan 401.[1], [2], [7]
- ✓Jangan anggap pembaruan saja cukup:
expectedResourcetetap nonaktif sebelum dikonfigurasi, dan tanpaAuthInfo.resourcesemua permintaan ditolak.[1] - ✓Tinjau log akses dan telemetri validasi untuk menemukan audience yang tidak terduga; cabut atau rotasi kredensial hanya jika bukti menunjukkan kemungkinan penyalahgunaan.[1]
Sumber
- Advisory keamanan GitHub GHSA-rvq5-wwqv-78pq
- Pull request #2930 MCP TypeScript SDK: expectedResource untuk requireBearerAuth
- Catatan rilis MCP TypeScript SDK 1.32.0
- MITRE CWE-863: Otorisasi Tidak Benar
- 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