Powierzchnia ataku MCP to transport, nie protokół
Piętnaście advisory w dziesięć dni i prawie żadne nie dotyczy samego Model Context Protocol. Dotyczą hydrauliki pod spodem oraz systemu ocen, który nie potrafi opisać szkody w kształcie agenta.
Dziesięć dni advisory, a najbardziej rzuca się w oczy to, czego w nich nie ma. Prawie żadne nie opisuje błędu w samym Model Context Protocol. Opisują kod, który go przenosi: transporty, nakładki, serwery napisane w jedno popołudnie, żeby wystawić narzędzie agentowi.
Lista dozwolonych i powłoka znów się rozjechały
Najgorszy z nich to czyste nieuwierzytelnione wykonanie kodu, a mechanizm warto przeczytać powoli. Funkcja walidująca sprawdzała nazwę pliku wykonywalnego wobec listy dozwolonych. Nie zaglądała do argumentów. Argumenty poszły dalej, bez zmian, do tego, co uruchamia podproces.
Więc lista mówi tak dozwolonemu binarium, a to dozwolone binarium jest akurat takim, które wykona dowolny napis, jaki mu podasz. Nic nie zostało obejście. Sprawdzenie zrobiło dokładnie to, co miało zrobić, tylko na innym obiekcie niż ten, który miał znaczenie.
To samo zdanie napisaliśmy kilka dni temu o trzech agentach do kodowania: walidacja oglądająca polecenie jako zwykły napis rozjeżdża się z powłoką, która je wykonuje. To jest ta sama porażka z naklejką MCP.
To transporty są powierzchnią
Dwa kolejne z tego samego projektu robią ten wzorzec jawnym. Endpoint dla transportów SSE i streamable-HTTP brał URL i słownik nagłówków wprost od wywołującego i wykonywał żądanie. Atakujący ustawia Authorization albo Cookie i sięga do usług wewnętrznych z doklejonymi poświadczeniami. Odpowiedzi nie wracają, więc to atak w ciemno, a w ciemno wystarczy, kiedy samo żądanie zmienia stan.
Gdzie indziej serwer w Go wystawia nasłuch Streamable HTTP na localhoście, pomija uwierzytelnianie, gdy zmienna z tokenem jest nieustawiona, i nie waliduje ani Host, ani Origin. Powiązanie z localhostem sprawia wrażenie granicy. Nie jest nią, bo przeglądarka na tej samej maszynie chętnie wyśle żądanie za atakującego, a bez sprawdzenia Origin serwer nie odróżni jednego od drugiego.
Nic z tego nie jest wadą protokołu. Specyfikacja nikomu nie każe ufać URL-owi podanemu przez wywołującego i nie twierdzi, że interfejs pętli zwrotnej jest mechanizmem uwierzytelniania. Błędy siedzą w hydraulice, która nim mówi, czyli w tej części, którą każdy pisze sam.
Łącznie z oficjalnym SDK
Najcichszy, a najbardziej pouczający przypadek jest w oficjalnym SDK, a nie w czyimś projekcie na boku. Jego klient HTTP czyta strumień zdarzeń i dokleja każdy fragment do bufora, który opróżnia się dopiero po nadejściu separatora. Serwer, który nigdy nie wyśle separatora, nie robi nic nielegalnego, po prostu nigdy nie kończy zdania. Klient słucha dalej, a bufor rośnie.
To nie jest sprytny exploit. To parser napisany pod współpracującego rozmówcę, wypuszczony do świata, w którym rozmówcę wybiera ten, kto skonfigurował agenta.
Prompt injection ma już CVE i dwie różne oceny
Ostatni przypadek znaczy więcej niż jego własny produkt. Zatrute instrukcje, dostarczone przez legalną funkcję i podane przez MCP, posłużyły do wyciągnięcia z agenta poświadczeń ze środowiska. Ma identyfikator, advisory i poprawkę, co jest postępem.
Ma też dwie oceny podstawowe, od tego samego oceniającego, dla tej samej wady:
CVSS 3.1 -> 9.0 CRITICAL CVSS 4.0 -> 6.4 MEDIUM
Ta różnica to nie niechlujstwo. To nowszy standard robiący coś, czego starszy nie potrafi: oddziela to, co dzieje się z systemem podatnym, od tego, co dzieje się ze wszystkim za nim. Przy prompt injection system podatny jest ledwo draśnięty. Cała szkoda ląduje na systemach, do których agent sięga w następnym kroku.
W starszym standardzie ta szkoda nie ma gdzie pójść poza oceną podstawową, więc wychodzi Critical. W nowszym przenosi się do własnych kolumn i liczba w nagłówku spada o ponad dwa i pół punktu. Żadna z nich nie jest błędna, i na tym polega problem: zespół triażujący po samej ocenie potraktuje to samo znalezisko jako alarm albo jako pozycję w backlogu, zależnie od tego, który standard raportuje jego narzędzie.
Co z tym zrobić
- Zaktualizuj wymienione wersje z kroniki poniżej i najpierw sprawdź, czy MCP jest u Ciebie w ogóle włączone, zanim uznasz się za podatnego.
- Traktuj każdy serwer MCP jak niezaufanego rozmówcę. Ograniczaj bufory, ustawiaj limity czasu na strumienie i nigdy nie pozwól wywołującemu wybrać URL-a, który pobierzesz, ani nagłówków, które doklejasz.
- Localhost to nie uwierzytelnianie. Waliduj Host i Origin na każdym lokalnym nasłuchu, z którym rozmawia agent, bo inaczej przeglądarka gdzie indziej na tej maszynie przemówi za atakującego.
- Nie triażuj znalezisk agentowych po samej ocenie podstawowej. Pytaj, dokąd agent sięga, bo tam ląduje realny wpływ, a tego właśnie starsza ocena nie potrafi wyrazić.
- Chainlit, wstrzyknięcie polecenia: CVE-2026-45018 / GHSA-w3fx-mc44-mf6j, pip chainlit >= 2.4.0rc0 i <= 2.11.1, załatane w 2.12.0. Critical, CVSS 9.8, AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H. Publikacja 25 sierpnia 2026. Funkcja validate_mcp_command() sprawdza nazwę pliku wykonywalnego wobec listy dozwolonych i nie ogląda argumentów, które trafiają do StdioServerParameters bez zmian.
- Chainlit, SSRF: CVE-2026-45019 / GHSA-hvfh-5mj3-5f3j, ten sam zakres wersji i ta sama poprawka. High, CVSS 7.2, AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N. Endpoint POST /mcp dla transportów sse i streamable-http przyjmował URL i nagłówki od wywołującego bez walidacji. SSE podatne od 2.4.0rc0, streamable-http od 2.6.4. Poprawka dodaje listę allowed_urls i usuwa zastrzeżone nagłówki.
- genieacs-mcp: CVE-2026-55637, wersje przed 0.3.2. CVSS 4.0 podstawa 8.8 High. Transport Streamable HTTP otwiera nieuwierzytelniony nasłuch /mcp na domyślnym 127.0.0.1:8080, gdy MCP_AUTH_TOKEN jest nieustawiony, i nie waliduje nagłówków Host ani Origin, co otwiera drogę atakowi DNS rebinding.
- MCP PHP SDK: CVE-2026-53965, pakiet Composera mcp/sdk, oficjalny SDK dla PHP, wersje od 0.5.0 do 0.7.0. CVSS 4.0 podstawa 6.9 Medium, wpływ wyłącznie na dostępność. Klient HTTP dokleja każdy fragment strumienia SSE do bufora w pamięci bez górnego ograniczenia, opróżnianego dopiero po nadejściu separatora zdarzenia.
- Context7: CVE-2026-75130, do wersji 2.1.2 włącznie. Prompt injection przez funkcję Custom AI Instructions serwowaną przez jego serwer MCP, wykorzystany do wyprowadzenia poświadczeń ze środowiska. NVD podaje DWIE oceny od tego samego wtórnego oceniającego: CVSS 4.0 podstawa 6.4 Medium oraz CVSS 3.1 podstawa 9.0 Critical.
- Piętnaście to liczba, którą nasz własny skaut wyciągnął z GHSA i NVD w oknie dziesięciu dni przy naszym zestawie zapytań. To nie jest spis powszechny ekosystemu, a inny zestaw zapytań da inną liczbę.
- NVD oznacza wszystkie te wpisy jako Received, czyli nieprzeanalizowane przez NVD. Każda ocena powyżej pochodzi od CNA albo wtórnego oceniającego, nie z własnej analizy NVD.
- Niczego z tego nie odtworzyliśmy i nie zaobserwowaliśmy żadnej próby wykorzystania. Nasz publiczny sensor jest wyłączony, więc nie mamy telemetrii ani skuteczności detekcji.
- Nie wiemy, czy to realny wzrost, czy po prostu więcej osób patrzy. Liczba advisory mierzy uwagę, a nie liczbę istniejących błędów.
- Przy Context7 nie potrafimy powiedzieć, która z dwóch ocen lepiej opisuje ryzyko. Obie pochodzą z tego samego źródła i żadnej nie odtworzyliśmy.
- 01GHSA-w3fx-mc44-mf6j: wstrzyknięcie polecenia w Chainlit przez transport MCP stdio ↗
- 02GHSA-hvfh-5mj3-5f3j: SSRF w Chainlit przez transporty MCP SSE i streamable-http ↗
- 03CVE-2026-55637: DNS rebinding na transporcie Streamable HTTP w genieacs-mcp ↗
- 04CVE-2026-53965: nieograniczony bufor SSE w oficjalnym MCP PHP SDK ↗
- 05CVE-2026-75130: prompt injection w Context7 przez Custom AI Instructions ↗
- 06Specyfikacja Model Context Protocol ↗

