FlawOpen

flawopen.com/Teardowns/cve-2026-105699-langflow-mcp-cross-project-file-disclosure

● CVE-2026-105699 · CVSS v4 7.1 · Tinggi
Riset Keamanan · FlawOpen

CVE-2026-105699: Kebocoran Berkas MCP Langflow

Langflow mengautentikasi koneksi MCP, tetapi tidak mengotorisasi setiap berkas yang diminta. Pengguna dapat membaca berkas alur milik pengguna lain; pemeriksaan kepemilikan diperbaiki pada 1.9.1.[1], [2], [5]

Vektor CVSSCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
💡 Penjelasan Sederhana (ELI5)

Bayangkan hotel memeriksa kartu kunci Anda, lalu menyerahkan koper dari kamar mana pun asalkan Anda menyebut labelnya. Kartu hanya membuktikan Anda boleh masuk hotel, bukan bahwa koper tamu lain milik Anda. Pembacaan MCP Langflow harus memeriksa pemilik dan proyek sebelum membuka berkas.[1]

Konsep Kunci & Istilah

Model Context Protocol (MCP)
Protokol yang memungkinkan aplikasi AI meminta alat dan sumber daya dari server. Server tetap harus mengotorisasi setiap objek yang diminta.[1]
Endpoint MCP khusus proyek
Koneksi MCP Langflow yang terikat pada satu proyek. Akses ke endpoint tersebut tidak memberikan akses ke berkas semua proyek.[1]
resources/read
Operasi MCP yang meminta server mengembalikan sumber daya yang ditentukan oleh URI.[1]
Otorisasi tingkat objek
Pemeriksaan apakah pengguna terautentikasi boleh mengakses catatan atau berkas tertentu, bukan sekadar endpoint.[1], [6]
CWE-639
Bypass otorisasi melalui kunci yang dikendalikan pengguna: mengubah pengenal memungkinkan akses ke catatan milik pengguna lain.[6], [2]

Pemetaan kerangka kerja

  • Referensi CWE untuk kelemahan yang dijelaskan dalam panduan ini: CWE-639

Analisis Akar Masalah (Root Cause)

Pada Langflow versi 1.6.8 sampai 1.9.0 yang terdampak, transport MCP khusus proyek mengautentikasi akses ke ID proyek pada URL koneksi. Setelah itu, handler resources/read menerima URI sumber daya, mengambil ID alur dan nama berkas, lalu meneruskannya ke storage_service.get_file() tanpa memastikan bahwa alur tersebut milik pengguna terautentikasi atau proyek saat ini. Lapisan penyimpanan membaca berdasarkan namespace dan nama berkas; lapisan itu tidak mengetahui izin pengguna atau proyek Langflow. Karena itu, pengguna yang memiliki akun dan akses ke endpoint MCP proyeknya sendiri dapat meminta berkas dari namespace alur pengguna lain. Perilaku global resources/list dan tools/list yang dilaporkan secara terpisah dapat membocorkan pengenal dan memudahkan pemilihan sasaran, tetapi tidak diperlukan untuk pembacaan. Ini adalah pelanggaran kerahasiaan antar pengguna yang memerlukan autentikasi, bukan akses anonim atau eksekusi kode. Catatan CVE menetapkan CVSS 4.0 7.1 High dan CWE-639. Langflow 1.9.1 memperbaiki jalur tersebut: handle_read_resource() mengambil pengguna terautentikasi dan mencari alur dengan syarat Flow.user_id == current_user.id; pada transport proyek, Flow.folder_id == project_id juga diwajibkan. Namespace tanpa izin ditolak sebelum akses penyimpanan. Patch juga menolak pemisah jalur dan urutan traversal, memeriksa batas jalur pada operasi baca/tulis/hapus, serta membatasi daftar global ke pengguna saat ini. Pengujian regresi maintainer menolak pembacaan alur pengguna lain.[1], [2], [3], [5]

Alur Serangan Langkah demi Langkah

Langkah 1

Pengguna masuk ke endpoint MCP proyek miliknya

Penyerang memerlukan akun Langflow dan akses ke setidaknya satu koneksi MCP khusus proyek. Masalah ini tidak melewati login.[1]

Langkah 2

Klien meminta URI sumber daya

Permintaan MCP resources/read berisi URI dengan bagian jalur terakhir yang menentukan namespace alur dan nama berkas.[1]

Langkah 3

Handler rentan memercayai pengenal

handle_read_resource() mengambil ID dan nama, tetapi tidak mengaitkan alur dengan pengguna atau proyek endpoint.[1], [3]

Langkah 4

Penyimpanan membaca berdasarkan namespace

storage_service.get_file() mengembalikan berkas dari namespace yang diberikan. Penyimpanan tidak memiliki konteks kepemilikan pengguna.[1]

Langkah 5

Respons melintasi batas pengguna

Peminta dapat menerima berkas alur pengguna lain. Daftar global dapat membocorkan pengenal, tetapi tidak diperlukan untuk mengeksploitasi pemeriksaan otorisasi yang hilang.[1], [2]

Kode Sumber: Rentan vs Aman

Ini adalah cuplikan Python terfokus dari jalur kode yang dilaporkan, bukan aplikasi mandiri. Jalur rentan menganggap namespace yang diberikan klien sebagai otoritas yang cukup. Perbaikan 1.9.1 terlebih dahulu mencari alur dalam cakupan pengguna terautentikasi dan, untuk transport MCP proyek, proyek saat ini; barulah penyimpanan boleh membacanya. Patch juga memvalidasi nama berkas dan menerapkan batas jalur pada lapisan penyimpanan agar jalur baca/tulis/hapus lain tidak dapat melewati pemeriksaan. Letakkan otorisasi pada layanan yang mengetahui pengguna dan proyek; adaptor penyimpanan tidak dapat menyimpulkan kepemilikan. Cakupan cuplikan: handler sebenarnya juga mengizinkan file di bucket pengguna hanya jika namespace sama dengan ID pengguna terautentikasi itu sendiri dan server tidak dibatasi ke proyek. Cabang terpisah ini tidak ditampilkan; cuplikan tidak berarti akses ke namespace sembarang. Suite regresi upstream mencakup test_handle_read_resource_denies_other_users_flow, yang memastikan pembacaan lintas pengguna ditolak.[1], [3], [4], [7]

Cuplikan sumber: mcp_utils.py — cuplikan kode terkait

IMPLEMENTASI RENTAN
# Kutipan jalur baca yang terdampak: ID yang diuraikan langsung diteruskan ke penyimpanan.
content = await storage_service.get_file(
    flow_id=flow_id,
    file_name=filename,
)
PERBAIKAN AMAN & KUAT
# Reduksi batas otorisasi versi 1.9.1 yang mengikuti struktur sumber.
current_user = current_user_ctx.get()
query = select(Flow).where(
    Flow.id == namespace_id,
    Flow.user_id == current_user.id,
)
if project_id is not None:
    query = query.where(Flow.folder_id == project_id)
flow = (await session.exec(query)).first()
if flow is None:
    raise ValueError("Resource not found or access denied")
content = await storage_service.get_file(
    flow_id=namespace_id,
    file_name=filename,
)

Daftar Periksa Penguatan Sistem Rekayasa

Sumber