Abstrakcyjna ilustracja techniczna na ciemnogranatowym tle: półprzezroczysta obudowa mieści stos małych zaokrąglonych paneli, a pojedynczy nieoznaczony ciemny kanał opada od spodu tego stosu prosto przez dno obudowy do niższej, nieoświetlonej komory. Obok kanału trzy małe blade bramki stoją zamknięte na półce, podczas gdy sam kanał przechodzi między nimi, a na jego drodze nie ma żadnej bramki. Cienka bursztynowa linia wchodzi do obudowy z lewej strony i znika w stosie. Brak tekstu, brak ludzi, brak logo organizacji, brak dosłownego przedstawienia jakiegokolwiek rzeczywistego systemu.
AI Safety Incidents

MaxKB dołączył narzędzie powłoki do każdego asystenta obsługującego narzędzia i nigdy nie ograniczył do niego dostępu

Autor

Alistair Wren

Data publikacji

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

MaxKB, open-source'owa platforma asystenta przedsiębiorstwa publikowana w organizacji GitHub 1Panel-dev, zbudowała swoich agentów czatu na frameworku, który po cichu dodaje narzędzie powłoki, gdy tylko przekazany zostanie backend obsługujący powłokę — a MaxKB nigdy nie usunął tego narzędzia ani nie poprosił nikogo o zatwierdzenie jego użycia. Wada to CVE-2026-77521, opublikowana jako biuletyn GitHub GHSA-f36j-f34j-h3rx 2 września 2026 r. i oceniona na 10,0 na 10 w CVSS 3.1 w przypadku publicznego lub wbudowanego asystenta. Lasso Security, które ją znalazło i zgłosiło, wykazało, że wiadomość czatu — lub tekst, który asystent jedynie przyswaja poprzez wyszukiwanie albo przesłany dokument — może skłonić model do uruchomienia poleceń: w przypadku wdrożenia na gołym metalu bezpośrednio na hoście, a w przypadku oficjalnego kontenera poprzez wrapper, który według badaczy można obejść średnikiem. Żadne z cytowanych źródeł nie odnotowuje wykorzystania tej wady w rzeczywistych atakach. Własna ocena dotkliwości, ocena pewności i lista źródeł tego rekordu znajdują się w archiwum incydentów AI, obok sąsiednich wpisów dotyczących MaxKB i narzędzi agentowych z tej samej partii ujawnień.

MaxKB to produkt do samodzielnego hostowania służący do budowania asystentów opartych na wyszukiwaniu: operator tworzy asystenta, przypisuje mu możliwości — narzędzia, serwery Model Context Protocol, umiejętności, podaplikacje — podłącza bazę wiedzy zbudowaną z przesłanych dokumentów lub zindeksowanych stron internetowych, a następnie udostępnia asystenta albo przez uwierzytelnioną konsolę, albo jako publiczny, osadzany widget czatu. Ta wszechstronność jest źródłem ekspozycji. Warunek wyzwalający z biuletynu bezpieczeństwa nie jest nietypową konfiguracją, lecz zwyczajną: każdy asystent z co najmniej jedną przypisaną możliwością kieruje swój czat przez dotkniętą ścieżkę agenta, natomiast czat bez przypisanych możliwości tego nie robi. W opracowaniu Lasso projekt opisano jako jeden z szerzej przyjętych w swojej kategorii i zauważono, że MaxKB jest zwykle wdrażany jako usługa wielodostępna — co sytuuje polecenie uruchamiane jako użytkownik aplikacji pod modelem dzierżawy, a nie w obrębie wycinka należącego do jednego dzierżawcy.

Narzędzie powłoki pojawiło się wraz z frameworkiem, a nie z produktem

MaxKB buduje tych agentów za pomocą biblioteki deepagents firmy LangChain, przypiętej do wersji 0.6.11 w pliku pyproject.toml projektu zarówno w tagu podatnym, jak i w bieżącym. W apps/application/flow/tools.py, w wierszu 467 tagu v2.10.3-lts, projekt wywołuje create_deep_agent z backendem ustawionym na SandboxShellBackend, podklasę MaxKB, która uruchamia polecenia na hoście. Zgodnie z biuletynem doradczym deepagents automatycznie wstrzykuje zestaw narzędzi, gdy w ten sposób zostanie przekazany backend powłoki: execute, ls, read_file, write_file, edit_file, glob i grep. Nie są one częścią argumentu tools=list, który zawiera wyłącznie narzędzia samego operatora, narzędzia MCP i narzędzia umiejętności. Nie można ich usunąć z interfejsu ani poprzez konfigurację.

MaxKB również nie przekazuje excluded_tools, argumentu bibliotecznego, który by je usuwał. Komunikat doradczy starannie wyjaśnia, dlaczego ma to znaczenie nawet jako środek zaradczy: excluded_tools „usuwa narzędzie z informacji przekazywanych modelowi, a nie z executora”. Rozróżnienie między narzędziem, którego model nie zna, a narzędziem, którego nie można uruchomić, to cały ten błąd w pigułce.

Bramka, która wymienia trzy narzędzia i pomija czwarte.

Mechanizm human-in-the-loop w tym samym wywołaniu to jedna linia i wylicza trzy operacje: interrupt_on={"write_file": False, "read_file": False, "edit_file": False}. Zapis pliku, odczyt pliku i edycja pliku są nazwane. Wykonywanie poleceń w ogóle nie jest kluczem w słowniku. W interpretacji biuletynu doradczego oznacza to, że nie jest wymagane zatwierdzenie dla execute — trzy operacje systemu plików są nazwane i jawnie ustawione tak, aby nie powodować przerwania, a narzędzie powłoki nie jest w ogóle nazwane.

Poskładane razem, ścieżka wygląda tak: niezaufany tekst dociera do modelu, model wywołuje execute, a polecenie zostaje uruchomione. Komunikat wskazuje dwa sposoby, w jakie może dotrzeć niezaufany tekst. Bezpośredni to czat — publiczny lub osadzony widget albo rozmowa innego dzierżawcy. Pośredni to treść, którą przyswaja asystent: dokument RAG, przesłany plik albo strona internetowa, którą platforma indeksuje do bazy wiedzy. Wpis Lasso ukonkretnia drugą drogę, zauważając, że „zbiór osób, które mogą umieścić tekst przed modelem, jest większy niż zbiór osób, które mogą z nim rozmawiać”.

W instalacji bare-metal polecenie jest po prostu poleceniem.

To, co MaxKB robi w zakresie izolacji, rozgrywa się w apps/application/flow/backend/sandbox_shell.py, a w wersji v2.10.3-lts zaczyna się od wartości domyślnej. W wierszu 9 znajduje się _enable_sandbox = bool(int(CONFIG.get("SANDBOX", 0))), a SANDBOX nie występuje w Config.defaults w apps/maxkb/conf.py. Wobec braku jawnego ustawienia MAXKB_SANDBOX wartość wynosi zero, gałąź wrappera w wierszu 65 jest pomijana, a execute dociera do subprocess.run z shell=True bezpośrednio na hoście, jako użytkownik uruchamiający usługę — root, zgodnie z sformułowaniem z komunikatu doradczego, jeśli usługa działa jako root.

To jest konfiguracja, której badacze użyli do swojego proof of concept na hoście. Uruchomili prawdziwy kod MaxKB ze źródeł z nieustawioną zmienną MAXKB_SANDBOX, utworzyli asystenta z jednym podłączonym narzędziem i poprosili go w jednej wiadomości czatu o uruchomienie poleceń informujących o systemie. Narzędzie execute zadziałało i zapisało plik, którego zawartością były wyniki uname, id i sw_vers samego hosta — wyniki, co odnotowuje biuletyn, potwierdzono jako nieobecne w żadnym kontenerze. Lasso odnotowuje również granicę tego, co to powstrzymało: model odmówił obsługi pliku dowodowego o oczywistej nazwie, ale nieszkodliwe sformułowanie operacyjne nie zostało odrzucone. Dopasowanie modelu, ich słowami, jest „częściowym spowalniaczem, a nie mechanizmem kontrolnym”.

Na oficjalnym obrazie sandbox działał, a mimo to doszło do wycieku.

Oficjalny kontener ustawia MAXKB_SANDBOX=1 w obrazie bazowym, w pliku installer/Dockerfile-base w wierszu 48, więc wrapper jest tam aktywny — a wrapper to druga wada. Budował jeden ciąg: env -i LD_PRELOAD=/opt/maxkb-app/sandbox/lib/sandbox.so, po którym następowało gosu sandbox, a potem polecenie dostarczone przez model, przekazywany do powłoki działającej jako root. Ponieważ polecenie było interpolowane jako tekst, tylko jego pierwszy token znajdował się pod gosu. Każdy średnik, potok, przekierowanie lub podstawienie polecenia w danych wyjściowych modelu był oceniany przez zewnętrzną powłokę roota, zanim sandbox w ogóle go zobaczył.

Opis Lasso przedstawia działający schemat tego: ładunek env -i LD_PRELOAD=... PATH="$PATH" gosu sandbox ls; whoami; id, w którym ls jest ograniczone, whoami nie, a wszystko po nim działa bez ograniczeń. W testach badacze zapisali plik należący do roota za pomocą przekierowania, podczas gdy wewnętrzne polecenie w piaskownicy zostało zablokowane. Co pogarsza sprawę, ani installer/Dockerfile, ani installer/Dockerfile-base nie zawiera dyrektywy USER, więc obraz aplikacji działa jako UID 0 — biuletyn bezpieczeństwa potwierdza uzyskanie uprawnień roota w czasie działania. Kontener mimo to wykonywał polecenia, a piaskownica decydowała jedynie, które z nich były kosmetycznie przypisane użytkownikowi o niskich uprawnieniach.

Pełny opisany przez Lasso przebieg ataku wcale nie wymaga dostępu do celu. Atakujący umieszcza polecenia na stronie internetowej, czeka, aż agent ofiary zindeksuje ją w bazie wiedzy, a następnie ofiara zadaje zwykłe pytanie. Odpowiedź wraca poprawna i wiarygodna; wstrzyknięty curl został już uruchomiony na serwerze atakującego. W biuletynie doradczym zauważono, że badacze testowali wyłącznie własne wdrożenia, a nie żadną zewnętrzną ani hostowaną instancję MaxKB.

Co wynika ze źródeł, a czego po prostu nie zmierzono

Mechanizm, dwa tryby wdrożenia, przypisanie autorstwa i wydanie z poprawką są spójne w czterech dokumentach: advisory GitHub, rekordzie NVD opublikowanym 21 września 2026 r., własnym opracowaniu technicznym Lasso z 10 września 2026 r. oraz raporcie GBHackers z 22 września 2026 r., który jest jedynym niezależnym materiałem medialnym znalezionym dla tego CVE. Żadne źródło nie kwestionuje żadnej części tego ustalenia, a archiwum odnotowuje ten wpis jako niekwestionowany na najwyższym poziomie pewności.

To, czego źródła nie zawierają, to jakakolwiek miara ekspozycji. Nie ma liczby wdrożeń MaxKB, liczby asystentów dostępnych z internetu ani osadzonych, wyniku skanowania, telemetrii ani wskazanego poszkodowanego. Nic w materiale nie pokazuje, że luka została wykorzystana przeciwko komukolwiek, i ocena wykorzystania samej CISA się z tym zgadza: blok SSVC dołączony do rekordu NVD w dniu 22 września 2026 r. ocenia wykorzystanie jako „poc”, automatyzowalność jako „yes”, a wpływ techniczny jako „total”. Model EPSS FIRST oszacował prawdopodobieństwo wykorzystania w ciągu najbliższych 30 dni na 1,05 proc., co odpowiada 64. percentylowi, na dzień 27 października 2026 r., a CVE nie występuje w katalogu CISA Known Exploited Vulnerabilities z datą 27 października 2026 r. Sama ocena archiwum odzwierciedla te same dowody: waga wysoka, rzeczywista szkoda fałszywa.

Wartość 10.0 zasługuje na wyraźne określenie swojego zakresu, ponieważ jest to liczba najczęściej cytowana bez kontekstu. To ocena dla przypadku publicznego lub osadzonego asystenta, w którym wektor CVSS ma postać AV:N/AC:L/PR:N/UI:N/S:C — osiągalność sieciowa, brak uprawnień, brak interakcji użytkownika, ze zmianą zakresu, ponieważ polecenie wewnątrz asystenta przechodzi do systemu operacyjnego hosta. Ocena należy do CNA, a CNA jest tutaj program doradczy GitHuba, na który wskazuje również identyfikator źródła rekordu CVE. NVD podaje ten sam wektor jako metrykę dodatkową i na dzień 28 października 2026 r. wymienia wpis ze statusem „Deferred”, co oznacza, że NVD opublikowało analizę podmiotu przypisującego, a nie własną.

Rendered two-column card with the kicker 'MAXKB · CVE-2026-77521' and the title 'What the sources establish, and what they do not', subtitled with its sources: GHSA-f36j-f34j-h3rx of 2 September 2026, the NVD record of 21 September 2026, Lasso Security's write-up of 10 September 2026, GBHackers of 22 September 2026, FIRST EPSS, the CISA KEV catalogue and the repository tags. The left column, headed 'Established' in blue, lists eight items: CVSS 3.1 base score 10.0 with the vector AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H for a public or embedded assistant; CWE-78 OS command injection, CWE-250 unnecessary privileges and CWE-749 exposed dangerous method; deepagents 0.6.11 auto-adding execute to any shell backend, with no excluded_tools passed by MaxKB; the approval map covering write_file, read_file and edit_file with execute not a key in it; affected at or below 2.10.3-lts per the advisory and at or below 2.10.4-lts per Lasso Security's write-up; fixed in 2.10.5-lts, published 6 August 2026, 27 days before the advisory; the CISA SSVC assessment of 22 September 2026 with exploitation poc, automatable yes and technical impact total; and EPSS 1.05 percent at the 64th percentile on 27 October 2026 with no listing in the CISA KEV catalogue of that date. The right column, headed 'Not established, or not measured' in amber, lists seven items: no exploitation in the wild recorded by any cited source, with the archive recording real harm as false; no count of affected, exposed or internet-facing deployments; no named victim and no evidence of use in any intrusion; NVD status Deferred, so the 10.0 is the assigner's analysis rather than NVD's; disagreement between the two primary sources on the affected range boundary; the researchers' testing confined to their own deployments; and no detection or triage guidance for either deployment mode. A footer reads 'Card rendered by OrcaRouter. The 10.0 is scored for a public or embedded assistant; the archive grades the record high.' The OrcaRouter logo is composited in the bottom-right corner.

Poprawka została udostępniona miesiąc przed publikacją biuletynu bezpieczeństwa.

Chronologia biegnie wstecz od publikacji i jest najmniej intuicyjną częścią zapisu. Lasso zgłosił tę wadę prywatnie za pośrednictwem kanału doradczego GitHuba 8 lipca 2026 r. MaxKB odpowiedział następnego dnia, zawężając zgłoszenie do oficjalnego obrazu i prosząc o dowód koncepcji w kontenerze; badacze dostarczyli go wraz z obejściem piaskownicy 10 lipca. Poprawka w commicie 594f50f2 trafiła 9 lipca — dzień po zgłoszeniu — i przepisała sandbox_shell.py tak, aby ciąg poleceń modelu był najpierw analizowany, a prefiks gosu stosowano do każdego prostego polecenia, a nie tylko do pierwszego, przy czym każda lista argumentów jest ponownie ujmowana w cudzysłowy, aby podstawienie nie mogło przedostać się do powłoki nadrzędnej. W opisie Lasso zmiana ta jest przedstawiona jako stosowanie prefiksu gosu „do każdego prostego polecenia, nie tylko do pierwszego”.

Wydanie zawierające tę poprawkę, v2.10.5-lts, opublikowano 6 sierpnia 2026 r. Biuletyn GitHub pojawił się 2 września, NVD opublikowało CVE 21 września, dodano blok SSVC CISA, a GBHackers poinformowało o tym 22 września, natomiast własne opracowanie Lasso ukazało się 10 września — w środku tej sekwencji, a nie na jej początku. Operator śledzący tagi wydań, a nie kanały biuletynów, miał łatkę około cztery tygodnie przed ostrzeżeniem.

Granica wersji zasługuje na więcej uwagi, niż poświęca jej biuletyn, ponieważ dwa główne źródła są ze sobą sprzeczne, a kwestię rozstrzyga repozytorium. Pole formularza biuletynu podaje wersje objęte problemem jako „<= 2.10.3-lts", wraz z uwagą, że zweryfikowano to na wersji 2.10.3-lts oraz że podatna ścieżka „prawdopodobnie" dotyczy wszystkich wersji, które budują agentów w ten sposób. Własny opis Lasso podaje zakres objętych wersji jako „<= 2.10.4-lts". Tagi potwierdzają szerszy zakres: v2.10.4-lts, wydana 16 lipca 2026 r., zawiera ten sam 75-wierszowy plik sandbox_shell.py co v2.10.3-lts, a przepisany 311-wierszowy plik po raz pierwszy pojawia się w v2.10.5-lts. Operator korzystający z wersji 2.10.4-lts, który przeczytałby wyłącznie zakres podany w biuletynie, doszedłby do wniosku, że znajduje się poza nim. Nie znajdował się.

Rendered vertical timeline card with the kicker 'MAXKB · CVE-2026-77521' and the title 'Reported, fixed, released, disclosed', subtitled that the dates come from Lasso Security's disclosure timeline, the repository's release tags and commit metadata, the NVD record and GBHackers, and that every date is a single day. Ten dated entries run down a single spine: 8 July 2026, reported privately to 1Panel-dev through GitHub's advisory channel; 9 July 2026, fix commit 594f50f2 rewrites sandbox_shell.py and the vendor asks for a container proof of concept; 10 July 2026, the container proof of concept and the sandbox bypass supplied; 16 July 2026, v2.10.4-lts released, still carrying the 75-line unpatched sandbox_shell.py; 6 August 2026, v2.10.5-lts, the fixed release with a 311-line wrapper and gosu applied to every simple command; 2 September 2026, advisory GHSA-f36j-f34j-h3rx published with CVSS 10.0; 10 September 2026, Lasso Security publishes MaxKBypass; 21 September 2026, NVD publishes CVE-2026-77521, with the CISA SSVC added the next day and GBHackers reporting; 15 October 2026, v2.10.7-lts flips the code default SANDBOX from 0 to 1; 22 October 2026, v2.10.8-lts still builds the agent with SandboxShellBackend and still omits execute. A dark band at the foot headed 'The gap' reads that the fixed release preceded the advisory by 27 days, that v2.10.4-lts was released a week after the fix commit and does not contain the fix, and that the execute tool has never been gated because the approval map at v2.10.8-lts still names only write_file, read_file and edit_file. A footer reads 'Card rendered by OrcaRouter.' The OrcaRouter logo is composited in the bottom-right corner.

Czego poprawka nie zrobiła

To, co naprawia 2.10.5-lts, to wrapper: nie buduje już pojedynczego ciągu powłoki z uprawnieniami roota. Nie robi natomiast niczego w kwestii narzędzia. Bezpośrednia lektura repozytorium na tagu v2.10.8-lts, opublikowanym 22 października 2026, pokazuje, że agent jest nadal konstruowany z backend=SandboxShellBackend, a interrupt_on nadal zawiera dokładnie trzy klucze — write_file, read_file i edit_file — bez execute. Pierwsze dwie sugestie naprawcze z biuletynu bezpieczeństwa — domyślne oparcie na backendzie niewykonującym oraz dodanie "execute": True do mapy zatwierdzeń — nie występują w tym wydaniu.

Zalecenie fail-closed pojawiło się później, w wersji v2.10.7-lts, i ma znaczenie dla trybu wdrożenia, który był w najgorszej sytuacji. Wydana 15 października 2026 r. wersja zmienia wiersz w sandbox_shell.py z CONFIG.get("SANDBOX", 0) na CONFIG.get("SANDBOX", 1). Instalacja ze źródeł lub typu bare-metal, w której nigdy nie ustawiono tej zmiennej, ma teraz domyślnie włączony wrapper zamiast wyłączonego, co w wąskim sensie jest zaleceniem „fail closed on non-container deploys”. Dokument doradczy pod tym samym nagłówkiem wymagał jednak więcej — aby przepływ z możliwością wykonywania odmawiał uruchomienia, gdy środowisko uruchomieniowe sandboxa jest niedostępne — a osobno wymagał, aby wrapper nigdy nie budował ciągu poleceń dla powłoki roota. Po stronie kontenerów, co jest faktem, a nie zaleceniem: ani installer/Dockerfile, ani installer/Dockerfile-base nie zawierają dyrektywy USER w tagu v2.10.8-lts, więc obraz aplikacji nadal uruchamia się jako root.

Czytane łącznie, stan odnotowany na dzień 28 października 2026 r. przedstawia się następująco. Druga połowa luki — piaskownica, z której wydostał się średnik — została zamknięta, podobnie jak domyślne zachowanie fail-open we wdrożeniach na hoście. Pierwsza połowa — narzędzie execute, które przychodzi z obiektem backendu i nie jest kluczem w mapie zatwierdzeń — wciąż jest sposobem, w jaki MaxKB buduje asystenta z obsługą narzędzi. Własne zalecenie naprawcze badaczy było wąskie: zaktualizować do wersji 2.10.5-lts lub nowszej i uruchomić wersję Docker z włączoną piaskownicą. GBHackers przekazało tę samą instrukcję oraz szerszą listę dla administratorów — wyłączyć backendy agentów obsługujące powłokę, chyba że wykonanie kodu jest wyraźnie wymagane; wymagać zatwierdzenia przez człowieka przed każdą akcją execute; uruchamiać kontenery jako użytkownik inny niż root; oraz traktować strony pobrane przez crawler, dokumenty RAG i przesłane pliki jako niezaufane dane wejściowe.

Drugi rekord MaxKB z tej samej wrześniowej partii

Drugi wpis MaxKB w archiwum z tej partii to inna usterka z gorszym zakończeniem. CVE-2026-77516, również opublikowany w NVD 21 września 2026 r., to obejście uprawnień, a nie wstrzyknięcie poleceń: od wersji 2.0.0 do 2.9.2 członek przestrzeni roboczej o najniższej roli, któremu jawnie odmówiono dostępu do narzędzia przez WorkspaceUserResourcePermission, nadal mógł powiązać identyfikator tego narzędzia przez tool_ids, skill_tool_ids lub mcp_tool_ids i wykonać je przez ścieżkę dyspozycji agenta lub przepływu pracy. Ścieżka dyspozycji nie stosuje ponownie uprawnienia do poszczególnych narzędzi, którego egzekwują dedykowane trasy narzędzi, a wykonanie narzędzia odszyfrowuje init_params po stronie serwera, więc wywołujący otrzymuje poświadczenia przenoszone przez narzędzie, do którego odmówiono mu dostępu. Jego ocena wynosi 5.4, a opis NVD kończy się zdaniem, którego CVE-2026-77521 nie musi zawierać: „Na dzień tej analizy nie jest dostępna żadna poprawiona wersja”.

Kontrast jest użyteczny dla każdego, kto ocenia tę parę. Podatność, która uzyskała ocenę 10.0, miała poprawkę wprowadzoną w ciągu jednego dnia i wydaną miesiąc przed jej publikacją. Podatność, która uzyskała ocenę 5.4, nie miała opublikowanej poprawionej wersji w momencie publikacji jej CVE.

Abstract illustration on a dark navy field: a tall translucent shelf holds a row of small pale gate symbols, and a wide unbroken corridor runs beneath the shelf from left to right with nothing standing in it. At the corridor's midpoint a thin amber line drops down from the shelf above and joins the corridor floor, and a small cluster of glowing key-shaped tokens rests just past the join, out of reach of the gates. No text, no people, no organisation logos, no literal depiction of any real system.

To, co pozostaje naprawdę otwarte, jest mniejsze, niż sugeruje ocena, i większe, niż wynika z notatki o łatce. Odkrycie nie jest kwestionowane, a mechanizm został zweryfikowany od początku do końca w obu trybach wdrożenia przez zespół, który go odkrył. Ekspozycja jest całkowicie niezmierzona — nikt nie opublikował, ile asystentów MaxKB ma narzędzie, ile z nich jest osiągalnych dla niezaufanej strony ani ile działa na hoście bez piaskownicy — więc rzeczywiste skutki tej wady są funkcją nawyków wdrożeniowych, których nie liczy żadne z cytowanych źródeł. A ta część projektu, która doprowadziła ocenę do maksimum, nadal występuje w bieżącym wydaniu: funkcja uruchamiania poleceń, domyślnie dołączona, nieobecna w mapie, która najpierw pyta człowieka.