Zapnuté MCP v Chainlitu dovolovalo bez přihlášení spouštět příkazy na serveru
Kdo v Chainlitu ručně zapnul podporu MCP, vystavil rozhraní, přes které mohl nepřihlášený klient poslat příkaz operačnímu systému. Další chyba dovolovala serveru podstrčit adresu ve vnitřní síti i vlastní hlavičky požadavku. Verze 2.12.0 obě cesty zavírá, ale starou konfiguraci je před aktualizací nutné přepsat.

Chainlit je otevřený systém v Pythonu pro stavbu konverzačních aplikací s umělou inteligencí. Přes Model Context Protocol (MCP) může taková aplikace připojit další nástroje a zdroje dat. Právě rozhraní POST /mcp ale až do verze 2.11.1 nechávalo část rozhodování na klientovi, který se k němu připojil.
Projekt 25. srpna vydal Chainlit 2.12.0 a s ním dvě bezpečnostní opravy. Kritická CVE-2026-45018 dostala hodnocení 9,8 z deseti. Druhá, CVE-2026-45019, má známku 7,2 a týká se požadavků do vnitřní sítě. Obě platí pro vydání od 2.4.0rc0 do 2.11.1, jen když provozovatel nastavil features.mcp.enabled = true. Od verze 2.7.0 je MCP ve výchozím nastavení vypnuté.
Kontrola hlídala program, argumenty už ne
Pro připojení nástroje přes standardní vstup a výstup posílal klient serveru pole fullCommand, tedy celý příkaz včetně argumentů. Chainlit jej rozdělil na části a porovnal jméno spouštěného programu se seznamem povolených programů. Co následuje za ním, už nekontroloval. Některé povolené programy přitom umějí argumentem vyvolat další příkaz operačního systému.
Výsledek nebyla jen možnost spustit jiný nástroj MCP. Podle hlášení mohl nepřihlášený útočník, který se dostal k rozhraní, vykonat libovolný příkaz s právy procesu Chainlitu. Spuštění navíc nastalo dřív, než se dokončilo navázání spojení MCP, takže neúspěšné spojení útok nezastavilo. V horším případě tak šlo číst soubory a tajné údaje aplikace, měnit je nebo se ze serveru vydat dál do vnitřní sítě.
Samostatná chyba mířila na přenosy SSE a streamable-http. Klient u nich posílal cílovou adresu a volitelné hlavičky HTTP. Server neomezoval schéma, hostitele ani privátní adresy a hodnoty předal knihovně MCP. Útočník proto mohl přimět Chainlit, aby zavolal službu, která zvenku vůbec dostupná není, případně metadatovou službu cloudového stroje. Odpověď se mu sice nevrátila, takže šlo o takzvaný slepý SSRF, požadavek však mohl obsahovat i podstrčenou hlavičku Authorization nebo Cookie a provést změnu bez nutnosti číst výsledek.
Oprava nepřidává chytřejší filtr příkazu
Chainlit se nepokusil sepsat delší seznam zakázaných argumentů. Pole fullCommand z požadavku odstranil celé. Servery MCP pro přenos stdio teď předem zapisuje provozovatel do souboru .chainlit/config.toml jako položky [[features.mcp.servers]]. Klient pošle jen jejich jméno a server k němu dohledá vlastní příkaz. Hranice je tím zřetelná: návštěvník si vybírá z připravených možností, ale neskládá proces, který se spustí.
U spojení přes síť je nový výchozí stav rovněž zákaz. Uživatelské servery se musejí výslovně zapnout volbou features.mcp.user_servers.enabled a jejich cíle omezit neprázdným seznamem allowed_urls. Kontrola rozebírá schéma, hostitele, port i cestu, odmítá nejednoznačné zápisy cesty a vybrané nebezpečné hlavičky zahazuje. Přesměrování HTTP se už nesledují a cíl se znovu ověřuje u každého odchozího požadavku.
Oprava přesto nedělá ze zapnutého MCP bezúdržbovou funkci. Hlášení upozorňuje, že instalace bez nastaveného přihlašování dovolí anonymnímu klientovi vyvolat předem připravený server stdio i po aktualizaci. Příkaz už nezmění, může však zakládat další procesy. U uživatelských síťových serverů navíc zůstává hlavička Authorization povolená záměrně, protože ji připojená služba může potřebovat. Bezpečnost proto stojí i na úzkém seznamu adres a na přihlášení, ne pouze na čísle verze.
Aktualizace je záměrně nekompatibilní
Vydání 2.12.0 je na PyPI od 25. srpna. Kdo MCP nepoužívá, může na ně přejít běžně. Kdo je zapnuté má, musí nejdřív převést staré oddíly [features.mcp.sse], [features.mcp.stdio] a [features.mcp.streamable-http] na nový společný seznam serverů. Staré klíče aplikace při zapnutém MCP rozpozná a start ukončí chybou. Není to vedlejší rozbití kompatibility: tiché přijetí původního nastavení by zachovalo právě model, ve kterém klient dodává příkaz nebo adresu.
Kdo nemůže aktualizovat hned, má podle obou hlášení nastavit features.mcp.enabled = false. Tím zavře obě chyby současně. Omezení odchozího provozu ze serveru a zapnuté přihlašování snižují dopad, ale původní vadný návrh samy neopravují.
Časová osa ukazuje, že nešlo o opravu po veřejném závodě s útočníky. Výzkumníci ze SPL Security poslali nález projektu neveřejně 8. dubna a Chainlit zveřejnil podrobnosti spolu s opravenou verzí. Národní databáze zranitelností NVD převzala obě čísla tentýž den; u kritické chyby uvádí, že existuje ukázka zneužití. Veřejné hlášení ani databáze ale zatím netvrdí, že byla chyba zneužívána proti cizím systémům.
Zdroje
- Chainlit 2.12.0, bezpečnostní poznámky a průvodce převodem konfigurace, 25. srpna 2026
- GHSA-w3fx-mc44-mf6j a GHSA-hvfh-5mj3-5f3j, původní technická hlášení projektu
- CVE-2026-45018 a CVE-2026-45019, Národní databáze zranitelností NIST
- Chainlit 2.12.0 na PyPI, nezávislé potvrzení vydané verze a času zveřejnění balíčku