Wygenerowana abstrakcyjna ilustracja na głębokim granatowym tle. Szeroka konstrukcja mostowa w kolorze łupkowym rozciąga się przez kadr, a jeden prostokątny otwór na jej lewej ścianie jest otwarty i świeci bursztynowym światłem. Przez ten otwór strumień małych, identycznych bloków wylewa się na zewnątrz w poprzek delikatnej siatki przypominającej plan architektoniczny, przekraczając cienką kropkowaną cyjanową granicę narysowaną na pierwszym planie, nie napotykając przy tym przeszkody. W prawym dolnym rogu bloki zasilają niską półprzezroczystą kratownicę połączonych węzłów przypominającą magazyn pamięci. Nie pojawiają się żadne teksty, litery, liczby, ludzie, znaki towarowe ani logotypy organizacji. Logo OrcaRouter jest nałożone w prawym dolnym rogu białego paska poniżej grafiki.
AI Safety Incidents

RufRoot: jedno nieuwierzytelnione żądanie do mostka MCP Ruflo wykonało polecenia, ukradło klucze i zatruło pamięć AI

Autor

Rowan Sterling

Data publikacji

Najnowsze modele · 20Zobacz wszystkie modele →
Benchmarki: Artificial Analysis · aktualizowane codziennie
Powrót do wszystkich wpisów

W dniu 30 czerwca 2026, Noma Labs przekazała opiekunowi Ruflo działający exploit wymierzony w sam projekt. Dział badawczy Noma Security odkrył, że Ruflo — platforma open source do orkiestracji agentów, wcześniej wydana jako Claude Flow — była dostarczana z domyślnym wdrożeniem Docker Compose, które wiązało jej most Model Context Protocol do portu 3001 na wszystkich interfejsach sieciowych i nie wymagało żadnego uwierzytelniania. Pojedyncze żądanie HTTP do punktu końcowego /mcp wystarczyło, aby uruchomić polecenia powłoki wewnątrz kontenera jako użytkownik node, a z tej powłoki atakujący mógł odczytać każdy klucz API dostawcy LLM w środowisku, zrzucić każdą zapisaną rozmowę, uruchomić roje agentów rozliczane na klucze ofiary oraz zapisać instrukcje do magazynu uczenia AgentDB, które nadal sterowałyby odpowiedziami AI dla każdego użytkownika tej instancji. Luka to CVE-2026-59726, nazwana RufRoot, oceniona na CVSS 10.0 i naprawiona w 3.16.3 w ciągu 24 godzin. Żadne źródło, które czytaliśmy, nie podaje, by wykorzystano ją w rzeczywistych atakach. Własny wpis archiwum dotyczący tej luki, wraz z listą źródeł i oceną pewności, znajduje się w archiwum incydentów AI, obok innych wpisów dotyczących MCP i infrastruktury zarejestrowanych wokół niego.

Domyślne ustawienie, które otworzyło drzwi

Ruflo to, jak Noma Labs nazywa meta-harness agentów: samodzielnie hostowana warstwa dla rojów nawet 100 agentów, zbudowana dla Claude Code i OpenAI Codex, z długoterminową pamięcią i wbudowanym serwerem MCP do wywoływania narzędzi. Typowa konfiguracja to ta opisana przez Noma — sklonuj repozytorium, dodaj klucze API LLM, uruchom docker compose up -d. Domyślny plik compose projektu wiązał most z 0.0.0.0 na porcie 3001 i wiązał towarzyszący MongoDB ze wszystkimi interfejsami na 27017, z wyłączonym uwierzytelnianiem Mongo. Jak daleko to sięga, zależy od firewalla, grupy bezpieczeństwa i segmentacji sieci wokół wdrożenia; sformułowanie samego Noma jest takie, że każda instancja osiągalna z sieci była całkowicie podatna na wykorzystanie bez uwierzytelniania.

Most MCP to serwer Express.js, który zamienia żądania JSON-RPC przychodzące przez HTTP w wywołania wewnętrznej biblioteki narzędzi Ruflo. W podatnej linii biblioteka ta zawierała 233 narzędzia obejmujące dostęp do powłoki, operacje bazodanowe, zarządzanie agentami i przechowywanie pamięci. W artykule Nomy nie ma ogródek, co to oznacza: „Most MCP nie jest przypadkowym pomocniczym interfejsem debugowania; jest raczej centralnym układem nerwowym Ruflo. Każde wywołanie narzędzia, każda akcja agenta, każda operacja na pamięci przechodzi przez Most MCP”.

Warstwa uwierzytelniania nie istniała — nie była po prostu słaba. POST /mcp i POST /mcp/:group implementują protokół MCP JSON-RPC i przekazują przychodzące tools/call żądania bezpośrednio do wewnętrznej executeTool() funkcji. Ruflo wprawdzie utrzymywał listę blokowanych poleceń, AUTOPILOT_BLOCKED_PATTERNS, której celem było zatrzymanie niebezpiecznych operacji powłoki, ale biuletyn GitHub wyraźnie stwierdza, że "była egzekwowana wyłącznie w przepływie autopilota. POST /mcp i POST /mcp/:group ją omijały". Jedno nieuwierzytelnione wywołanie wskazujące ruflo__terminal_execute w rezultacie uruchomiło dowolne polecenia jako użytkownik node kontenera, odnotowany w biuletynie jako uid 1000, bez wymaganego tokenu, sesji ani wcześniejszej interakcji. Do tego, co nastąpiło, nie była potrzebna eskalacja uprawnień: dane uwierzytelniające, interfejsy API agentów, magazyn pamięci i baza danych były dostępne z tej powłoki.

Łańcuch, w ośmiu krokach

Noma Labs opublikowała ośmioetapowy dowód koncepcji i potwierdziła każdy etap na żywo przeciwko domyślnemu wdrożeniu Ruflo w AWS EC2, wykorzystując wywołania zwrotne poza pasmem (out-of-band callbacks) do Burp Collaborator w celu zweryfikowania wykonania i eksfiltracji. Etapy te nie są spekulacyjnymi konsekwencjami nałożonymi na teoretyczny błąd; to zademonstrowana sekwencja, a sekcja dotycząca remediacji w doradztwie jest napisana dla operatorów, którzy mogą już się w nim znajdować.

A hand-built HTML card headed 'The RufRoot chain, step by step', kicker 'RufRoot - CVE-2026-59726', subtitle 'Eight steps Noma Labs confirmed live against a default Ruflo deployment on AWS EC2'. Eight rows, each with a circled step number, the action, and what it yielded. 1, call tools/list: enumerate the 233 exposed tools. 2, call ruflo__terminal_execute over POST /mcp: shell inside the bridge container as node, uid 1000, verified by an out-of-band callback. 3, run printenv: every LLM provider API key in the container environment. 4, call ruflo__swarm_init and ruflo__agent_spawn: attacker-controlled agent swarms running on the victim's keys and compute. 5, call ruflo__agentdb_pattern-store: a fabricated SOC2 policy in the learning store, steering future output for all users. 6, query MongoDB on port 27017: every stored conversation, title and metadata. 7, write /app/beacon.js and inject it into index.js, then kill PID 1: a backdoor that survives the container restart policy. 8, clear shell history: no forensic trace. A footer cites Noma Labs and CVE-2026-59726, and marks step 5 as the step a patched redeploy does not undo.

Rozpoznanie następuje jako pierwsze, ponieważ lista narzędzi jest publiczna dla każdego wywołującego: tools/list zwraca wszystkie 233 wpisy bez poświadczenia. Wykonywanie poleceń wynika z tego samego punktu końcowego, a proof of concept Nomy potwierdził to za pomocą wywołania zwrotnego poza pasmem, a nie przez wnioskowanie z treści odpowiedzi. Etap środowiskowy jest tym, który zamienia kompromitację hosta w problem rozliczeniowy i utraty danych: plik compose przekazywał klucze dostawcy do kontenera, a procesy backendu dziedziczyły pełne środowisko przez { ...process.env }, więc pojedynczy printenv zrzucił je. Te klucze pozwoliły następnie ruflo__swarm_init i ruflo__agent_spawn uruchomić kontrolowane przez atakującego swarmy, które zużyły przydział i zasoby obliczeniowe ofiary.

Krok piąty to ten, który przetrwa włamanie. Używając ruflo__agentdb_pattern-store, Noma umieścił sfabrykowaną politykę zgodności z SOC2, która nakazała AI osadzać kontrolowany przez atakującego URL w każdym kolejno generowanym przez nią skrypcie wdrożeniowym. Ponieważ AgentDB istnieje właśnie po to, aby utrwalać dokładnie tego rodzaju wzorce, tak by zachowanie agenta poprawiało się między sesjami, wstrzyknięty wpis zachowywał się tak, jak system został zaprojektowany, by się zachowywać. „Przyszłe rozmowy generują wyniki pozostające pod wpływem atakującego, a użytkownik nie ma sposobu, aby to stwierdzić” — stwierdza opracowanie Nomy. Dark Reading, które zgłosiło tę lukę 29 lipca, zapytało zewnętrznego eksperta o to rozróżnienie: John Gallagher, wiceprezes Viakoo, nazwał to inną klasą problemu: „To nie jest wykorzystywanie luk w oprogramowaniu, to zatruwanie pamięci”.

Pozostałe kroki to konwencjonalne działania post-exploitation, wykonane z niezwykłą łatwością. MongoDB w wewnętrznej sieci Docker nie miało uwierzytelniania, więc atakujący zainstalowali klienta w /tmp, zrzucili rozmowy i przesłali je na zewnątrz. Trwałość uzyskano przez zapisanie /app/beacon.js, dodanie wiersza require('./beacon.js') do index.js i zabicie PID 1, po czym polityka restartu Dockera przywróciła kontener z aktywnym beaconem. Ostatnim krokiem było wyczyszczenie historii powłoki. Wszystko to wynikało z jednego nieuwierzytelnionego żądania; nic w domyślnym wdrożeniu nie zatrzymało tej sekwencji w żadnym momencie.

Poprawka — i ta część, której łatka nie zdoła dosięgnąć

Opiekun projektu udostępnił Ruflo 3.16.3 w ciągu 24 godzin od ujawnienia 30 czerwca, a GitHub opublikował poradnik bezpieczeństwa GHSA-c4hm-4h84-2cf3 w dniu 1 lipca 2026. Remediacja, śledzona w repozytorium jako ADR-166 i scalona w pull request 2521, zmienia ustawienia domyślne, zamiast tylko dodawać kontrolę:

• Most MCP wiąże 127.0.0.1 domyślnie; publiczne wiązanie wymaga MCP_AUTH_TOKEN, a proces przy starcie kończy działanie z komunikatem krytycznym, jeśli token jest nieobecny.

• Oprogramowanie pośredniczące tokenu Bearer z porównaniem w stałym czasie znajduje się przed mostem.

• terminal_execute jest ograniczany po stronie serwera przez MCP_ENABLE_TERMINAL=true, domyślnie wyłączony, a to ograniczenie jest egzekwowane w identyczny sposób na /mcp, /mcp/:group oraz w przepływie autopilota — brakujące ogniwo, które pozwalało ujawnionemu łańcuchowi dotrzeć do powłoki.

• MongoDB wymaga uwierzytelniania; do uruchomienia kontenera wymagane jest hasło root.

• Kontener bridge działa z systemem plików głównym tylko do odczytu z tmpfs, lista dozwolonych CORS zastępuje symbol wieloznaczny, a blokady regresji CI obejmują statyczną konfigurację i zachowanie w czasie działania.

Nic z tego nie usuwa wpisu, który został już zapisany w AgentDB. Komunikat doradczy zaleca operatorom dowolnej wystawionej instancji natychmiast zablokować porty 3001 i 27017 na zaporze sieciowej, wymienić klucze dostawcy, przeprowadzić audyt magazynu wzorców pod kątem wstrzykniętych wpisów agentdb_pattern-store i usunąć je, przeprowadzić audyt MongoDB pod kątem manipulacji oraz przebudować kontenery z czystych obrazów. Jego ostrzeżenie jest wyjątkowo bezpośrednie: „Samo ponowne wdrożenie z poprawką NIE cofa zatrucia”. Analiza Noma prowadzi do tej samej konkluzji — audyt magazynu wzorców jest częścią remediacji, a poprawka nie.

Powód jest strukturalny, a nie wynikający z niedbalstwa. Magazyn wzorców, który kształtuje przyszłe wyniki modelu, nie ma sposobu odróżnić legalnej wyuczonej instrukcji od tej zaszytej przez atakującego; obie trafiają jako wzorce, a system jest zbudowany tak, by im ufać. To zamienia lukę w sieci w problem integralności danych o nieznanym zakresie zaległości i sprawia, że pytanie dla operatora nie dotyczy już tylko tego, czy port był osiągalny, ale tego, co pamięć przechowuje teraz.

A hand-built HTML timeline card headed 'From disclosure to coverage', kicker 'RufRoot - disclosure timeline', subtitle 'Five dates, from the private report to the day the record was filed'. Six dated rows. 30 June 2026: Noma Labs discloses the flaw to Ruflo's maintainer with a working proof of concept. 1 July 2026: Ruflo 3.16.3 ships and GHSA-c4hm-4h84-2cf3 is published with CVSS 10.0. 9 July 2026: the CVE record for CVE-2026-59726 is published in the National Vulnerability Database, later marked Deferred. 29 July 2026: The Hacker News and Dark Reading report the flaw; Noma Labs publishes its research. 30 July 2026: SecurityWeek reports it, and the record is dated to this day. A separate amber note reads: no source we read reports exploitation in the wild at any point on this timeline. A footer cites The Hacker News, the GitHub advisory API, the NVD record and SecurityWeek.

Co jest ustalone, a co nie

Zapis techniczny ma tu pierwszeństwo i jest spójny. Komunikat bezpieczeństwa wymienia podatny pakiet (npm ruflo poniżej 3.16.3), wersję z poprawką, dokładne punkty końcowe, użytkownika kontenera i dwa porty; notatki wydania opiekuna projektu opisują ten sam łańcuch; opracowanie Nomy dostarcza szczegółów proof-of-concept; a niezależne redakcje — The Hacker News i Dark Reading 29 lipca 2026 r., SecurityWeek 30 lipca — relacjonują ten sam mechanizm, nie dodając sprzecznych szczegółów. Notatka badawcza Cloud Security Alliance z 5 sierpnia 2026 r. powtarza tę sekwencję i umieszcza ją obok wcześniejszych nieuwierzytelnionych luk w MCP i orkiestracji agentów, które śledziła. Archiwum ocenia pewność zapisu na A, bezsporną, i oznacza go jako przełomowy; jego ocena dotkliwości dla zapisu jest wysoka, odrębna od samego wyniku CVSS.

Jedną kwestię dotyczącą punktacji warto ująć precyzyjnie, ponieważ dwa podstawowe dokumenty są sprzeczne. GHSA-c4hm-4h84-2cf3 ma CVSS 10.0 na wektorze AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H — to zmiana zakresu podnosi go do maksimum. Kopia tego samego komunikatu bezpieczeństwa na stronie wydania 3.16.3 opisuje wynik jako „CVSS 9.8 krytyczny”. Rekord w National Vulnerability Database, sprawdzony 30 października 2026 r., opublikowany 9 lipca 2026 r. i opatrzony statusem Odroczony, zawiera GitHub 10.0 jako metrykę dodatkową i nie ma własnej oceny autorstwa NVD. Nie znaleźliśmy wyjaśnienia dla wzmianki o 9.8, a ten tekst tego nie rozstrzyga.

Liczby dotyczące adopcji są skromniejsze. Noma Labs opisywał projekt wówczas jako mający ponad 67 000 gwiazdek GitHub, około 10 milionów pobrań i około 1 miliona aktywnych użytkowników; The Hacker News, jak podsumowała Cloud Security Alliance, podał ponad 66 500 gwiazdek. Liczby pobrań i użytkowników są danymi samego Noma Labs i nie zostały niezależnie zweryfikowane. Liczba gwiazdek repozytorium na dzień 30 października 2026 r. wynosiła 80 198 — to sprawdzian zasięgu projektu, a nie miara narażenia, i żadne źródło nie opublikowało, ile wdrożeń było faktycznie osiągalnych z sieci.

A hand-built HTML card headed 'Established, and not', kicker 'RufRoot - evidence', subtitle 'What the advisory, the release notes and the research support, against what nobody has shown'. Two columns. The left column, headed 'Established', lists: CVE-2026-59726 affects npm ruflo below 3.16.3 and is patched in 3.16.3; the default compose file bound the MCP bridge to 0.0.0.0 on port 3001 and MongoDB to 27017 without authentication; POST /mcp and POST /mcp/:group reached 233 tools and terminal_execute with no credential, running as node, uid 1000; Noma Labs confirmed an eight-step chain live on AWS EC2 with out-of-band callbacks, including an AgentDB pattern injection; the advisory was published 1 July 2026 with CVSS 10.0 and the fix shipped within 24 hours of the 30 June disclosure; the archive record is confidence A, undisputed, no real harm recorded, GLOBAL, MCP and INFRA. The right column, headed 'Not established', lists: that anyone exploited the flaw in the wild; how many Ruflo deployments were actually network-reachable; that any instance's AgentDB was poisoned, since no audit results are published; whether 9.8 in the release notes or 10.0 in the advisory is the intended score; Noma's counts of 10M downloads and 1M active users, which no independent source confirms; that any operator received notice beyond the public advisory. A footer cites GHSA-c4hm-4h84-2cf3, the Ruflo 3.16.3 release notes, Noma Labs and SecurityWeek.

To, czego nie ustalono, jest częścią najłatwiejszą do wyolbrzymienia. Ani Noma, ani opiekun projektu, ani żadne medium, które czytaliśmy, nie twierdzi, że lukę wykorzystano w rzeczywistych atakach, a archiwum nie odnotowuje dla tego wpisu żadnych realnych szkód. Proof of concept Nomy uruchomiono na wdrożeniu, które badacze kontrolowali na EC2 — pokazuje to, co umożliwia instalacja domyślna, a nie to, czego doświadczyła jakakolwiek konkretna instancja produkcyjna. Nie opublikowano liczby wdrożeń Ruflo wystawionych na internet, żaden operator nie opublikował też wyników audytu AgentDB, więc zarówno populacja dotkniętych, jak i ilość istniejącej zatrutej pamięci pozostają nieznane. Zalecenie Cloud Security Alliance, by traktować ujawnione wdrożenia jako całkowicie skompromitowane, to postawa wobec ryzyka uzasadniona eksploatacją niewymagającą żadnej interakcji; nie jest to dowód, że doszło do włamania.

Dlaczego archiwum uznaje to za punkt orientacyjny

Przełomowa flaga archiwum opiera się na czymś bardziej konkretnym niż maksymalna ocena. Błąd zdalnego wykonania kodu o CVSS 10.0 w popularnej samodzielnie hostowanej usłudze to znajomy gatunek, a poprawka pojawiła się tutaj w ciągu 24 godzin. RufRoot wyróżnia to, że exploit zakończył się w własnym potoku uczenia AI, gdzie konwencjonalne remedium — aktualizacja, ponowne wdrożenie, zamknięcie portu — pozostawia wstrzykniętą instrukcję na miejscu, wciąż kształtującą odpowiedzi. Nota Cloud Security Alliance odczytuje to jako studium przypadku wzorca, który już udokumentowała w narzędziach agentowych, w tym w łańcuchu checkpointów LangGraph i nieuwierzytelnionej powierzchni AutoGen Studio, i przekonuje, że trwała pamięć używana do kształtowania zachowania agenta powinna być traktowana jako wrażliwy magazyn danych objęty monitorowaniem integralności, a nie jako pamięć podręczna.

To przeformułowanie jest praktycznym wnioskiem. Widocznym artefaktem tego incydentu jest załatana zależność i opublikowany komunikat doradczy; niewidocznym jest wszystko, co wzorzec może wciąż zawierać w AgentDB operatora, a nie ma żadnego opublikowanego narzędzia ani sygnatury, które pozwoliłyby odróżnić legalnie wyuczoną politykę od wszczepionej. W przypadku organizacji, które uruchomiły domyślny plik compose w sieci dostępnej z zewnątrz, użyteczną reakcją jest ta, którą podają zarówno Noma, jak i komunikat doradczy: założyć, że klucze zostały odczytane, przeprowadzić ich rotację i sprawdzić pamięć, zanim zaufa się odpowiedziom, które generuje.