Lista dozwolonych poleceń nie przechytrzy powłoki
Pięć sposobów na obejście bramki zatwierdzania poleceń w jednym agencie programistycznym, opublikowanych tego samego dnia. To nie jest pięć pomyłek, tylko jeden projekt: bramka czyta polecenie powłoki wyrażeniami regularnymi i liczy na to, że przeczyta je tak samo jak bash.
Agent programistyczny proponuje polecenie powłoki. Zanim ono się wykona, niewielki fragment kodu decyduje, czy zapytać człowieka, czy przepuścić je bez pytania. W Roo Code ten fragment kodu dostał właśnie pięć CVE jednego dnia i każde działa tak samo: bramka czyta polecenie na jeden sposób, powłoka na inny, a wykonuje się wersja powłoki.
Dwa parsery, jeden napis
Bramka zatwierdzająca polecenia powłoki jest, czy jej autorzy tego chcieli, czy nie, drugim parserem powłoki. Zanim porówna polecenia z listą, musi je wszystkie znaleźć w jednym napisie. Prawdziwym parserem jest bash, za którym stoją dekady gramatyki: reguły cytowania, podstawienia, przekierowania, rozwijanie wzorców i nowa składnia w każdym wydaniu. Bramka to kilka wyrażeń regularnych.
Wszędzie tam, gdzie te dwa parsery nie zgadzają się, gdzie polecenie się zaczyna i kończy, atakujący wybiera, którą wersję zobaczy bramka. Słabość przypisana czterem z pięciu rekordów nazywa się dokładnie tak: konflikt interpretacji. To najuczciwiej dobrane CWE, jakie widzieliśmy w tym roku.
>&echo X przekierowanie usunięte, reszta wygląda jak echo
echo \";X;\" cudzysłów z ukośnikiem maskuje separatory
echo ${ X; } funsub odczytany jako rozwinięcie parametru
echo *$(X) podstawienie znika razem ze wzorcem glob
$(echo X) wynik echo staje się poleceniemŻadne z nich nie wymaga sprytnego ładunku. Każde to zwykła składnia powłoki, której bramka po prostu nie modeluje. Ostatnie jest najczystsze: bramka sprawdza polecenie wewnętrzne, widzi niegroźne echo i zatwierdza. Powłoka uruchamia echo, a potem wykonuje to, co echo wypisało.
Dlaczego kolejna łatka by tego nie zamknęła
Kod miał już osobne sprawdzenie niebezpiecznych podstawień, czyli ręcznie spisaną listę form, które trzeba pokazać człowiekowi. Przypadek z wzorcem glob dostał własną etykietę, niepełną listę niedozwolonych danych, bo tym zawsze staje się lista znanych złych kształtów. Każde z tych obejść da się załatać jeszcze jednym wyrażeniem regularnym, a załatana bramka nadal będzie częściową kopią basha, która goni oryginał, a oryginał się zmienia: jedno z pięciu obejść używa składni, której starsze wydania basha w ogóle nie przyjmują.
Wyzwalaczem jest treść, nie użytkownik
Rekordy wskazują pośredni prompt injection jako drogę wejścia. Nikt tych poleceń nie wpisuje. Agent czyta README, zgłoszenie albo stronę WWW z instrukcjami, proponuje polecenie w jednym z powyższych kształtów, a bramka je zatwierdza, bo widoczny początek jest na liście. Zaufanie to powierzchnia ataku: liście ufano, że opisuje to, co się wykona, a opisywała tylko to, co bramce udało się sparsować.
Co konkretnie zrobić
- Wyłącz teraz automatyczne zatwierdzanie poleceń w Roo Code. Żaden rekord nie wskazuje wersji z poprawką, więc to ustawienie jest jedyną kontrolą, jaką masz. Każde polecenie trafi wtedy do człowieka.
- Sprawdź pod tym kątem każdego agenta programistycznego w firmie. Jeśli automatyczne zatwierdzanie polega na dopasowywaniu początku napisu dla powłoki, zakładaj, że ta sama klasa obejść istnieje, dopóki ktoś nie wykaże inaczej. Forki jednego kodu dzielą jeden parser.
- Jeśli budujesz agenty, przestań przekazywać napisy powłoce. Uruchamiaj narzędzia jako listę argumentów bez powłoki pośrodku albo odmawiaj automatycznego zatwierdzenia każdego polecenia, które zawiera jakikolwiek metaznak powłoki. Oba podejścia są toporniejsze niż parser i oba są poprawne.
- Postaw granicę pod agentem. Kontener albo sandbox bez Twoich poświadczeń ogranicza to, do czego dosięgnie zatwierdzone polecenie, niezależnie od tego, który parser dał się oszukać.
- Pięć rekordów CVE dla Roo Code, wszystkie nadane przez VulnCheck i opublikowane 13 października 2026: CVE-2026-110202 (usuwanie operatora przekierowania), CVE-2026-110203 (rozjazd maskowania cudzysłowów), CVE-2026-110204 (podstawienie polecenia w składni funsub), CVE-2026-110205 (token glob gubiący podstawienie polecenia) i CVE-2026-110206 (podstawienie polecenia w pozycji polecenia).
- Zakres podatnych wersji w każdym rekordzie: Roo Code od 0 do 3.54.0 włącznie, status domyślny: niepodatne. Żaden rekord nie wskazuje wersji z poprawką.
- Słabość: CWE-436, konflikt interpretacji, dla CVE-2026-110202, CVE-2026-110203, CVE-2026-110204 i CVE-2026-110206. CWE-184, niepełna lista niedozwolonych danych wejściowych, dla CVE-2026-110205.
- Oceny są identyczne dla wszystkich pięciu i wszystkie pochodzą od VulnCheck: CVSS 3.1 podstawa 8.8, AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H, oraz CVSS 4.0 podstawa 7.7, AV:N/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H.
- Mechanizm według rekordów: kod zatwierdzania w parseCommandLine() i getCommandDecision() decyduje, czy polecenie powłoki zaproponowane przez agenta zostanie zatwierdzone automatycznie, i w każdym z przypadków widzi polecenie z listy dozwolonych, na przykład echo, podczas gdy powłoka uruchamia polecenie zabronione. Rekordy wskazują pośredni prompt injection jako wyzwalacz, a CVE-2026-110205 podaje jako warunek włączone automatyczne zatwierdzanie. CVE-2026-110204 dotyczy bash w wersji 5.3 lub nowszej oraz ksh93.
- Wpis ADP agencji CISA dla CVE-2026-110204 (13 października 2026) klasyfikuje wykorzystanie jako proof of concept, automatyzowalność jako nie, wpływ techniczny jako całkowity. Pozostałe cztery rekordy nie mają oceny ADP.
- We wszystkich pięciu jako odkrywców wskazano Minqianga Gui i Siyu Lou. Status w NVD na 14 października 2026: Awaiting Analysis, więc NVD nie opublikowało własnej oceny.
- GitHub oznacza repozytorium RooCodeInc/Roo-Code jako zarchiwizowane, czyli tylko do odczytu. Ostatnie wydanie, v3.54.0 z 15 maja 2026, to górna granica podatnego zakresu.
- Czy poprawka gdziekolwiek istnieje. Rekordy nie podają wersji z poprawką, a zarchiwizowane repozytorium nie przyjmuje zmian. Badacze datują archiwizację na 16 maja 2026. API GitHuba tej daty nie podaje, więc to ich stwierdzenie, nie nasze.
- Opisy badaczy wskazują jako testowaną wersję commit z v3.53.0, a rekordy mówią o wersjach do 3.54.0. Cytujemy rekordy.
- Nie odtworzyliśmy żadnego z pięciu obejść. Wszystko opiera się na rekordach CVE i na opisach proof of concept od badaczy.
- Ile instalacji działa z włączonym automatycznym zatwierdzaniem poleceń, czyli w konfiguracji, która ma tu znaczenie. Nikt tego nie opublikował, a my nie mamy telemetrii: nasz publiczny sensor jest wyłączony.
- Czy forki i pochodne Roo Code odziedziczyły ten sam parser. Żaden nie pojawia się w tych rekordach i żadnego nie sprawdzaliśmy.
- 01CVE-2026-110202: obejście automatycznego zatwierdzania w Roo Code przez usunięcie operatora przekierowania ↗
- 02CVE-2026-110203: obejście automatycznego zatwierdzania w Roo Code przez rozjazd maskowania cudzysłowów ↗
- 03CVE-2026-110204: obejście automatycznego zatwierdzania w Roo Code przez podstawienie funsub ↗
- 04CVE-2026-110205: obejście automatycznego zatwierdzania w Roo Code przez token glob gubiący podstawienie ↗
- 05CVE-2026-110206: obejście automatycznego zatwierdzania w Roo Code przez podstawienie w pozycji polecenia ↗
- 06Rekord CVE-2026-110204 z oceną CISA ADP ↗
- 07Repozytorium RooCodeInc/Roo-Code, zarchiwizowane ↗
- 08Opis badaczy: podstawienie polecenia w pozycji polecenia ↗
