Pański agent ma pośrednika, którego Pan nie zweryfikował
Badacze kupili 28 płatnych routerów LLM API w Taobao, Xianyu i sklepach opartych na Shopify, a kolejne 400 darmowych zebrali w publicznych społecznościach. Na każdym zarejestrowali konto, przepuścili przez niego agenta kodującego działającego w piaskownicy, wykonali każde zwrócone wywołanie narzędzia i obserwowali, co się dzieje.1
Dziewięć z 428 przepisało wywołanie narzędzia na polecenie lub zależność kontrolowaną przez atakującego: jeden router płatny i osiem darmowych. Siedemnaście darmowych routerów użyło następnie poświadczenia-pułapki (canary) AWS, które zobaczyło w przesyłanym ruchu, a jeden opróżnił podłożony klucz Ethereum. Dwa z wstrzykujących routerów ukrywały to zachowanie. Jeden czekał 50 żądań, zanim zaczął działać, a drugi uaktywniał się tylko w sesjach w autonomicznym „YOLO mode” (trybie, w którym agent wykonuje polecenia bez potwierdzeń) pracujących nad projektami w Rust lub Go.1
Router LLM API to proxy warstwy aplikacji. Kończy połączenie TLS, czyta każde żądanie i każdą odpowiedź jako zwykły tekst i może przepisać wywołanie narzędzia, które agent właśnie ma wykonać. Autorzy artykułu nie znaleźli żadnego dużego dostawcy, który podpisywałby odpowiedzi z wywołaniami narzędzi, więc nic nie wiąże polecenia uruchamianego przez agenta z tym, co wygenerował model. Przetestowano cztery frameworki agentowe, w tym Claude Code i Codex, i żaden nie sprawdzał integralności odpowiedzi.1
Ten wpis ukazał się po raz pierwszy 10 kwietnia 2026 roku i powstał na podstawie abstraktu artykułu. 2 października 2026 roku napisałem go od nowa na podstawie pełnego tekstu. Wersja kwietniowa zawierała kilka błędów; są wymienione w sekcji „Co wersja kwietniowa zrobiła źle” pod koniec.
TL;DR
- Co może router. Stoi między klientem a dostawcą modelu jako skonfigurowany punkt końcowy, więc ma w postaci zwykłego tekstu każde żądanie i każdą odpowiedź i może zmienić jedno lub drugie, zanim przekaże je dalej.1
- Co zrobiło 428 routerów. Dziewięć wstrzyknęło złośliwy kod do zwracanych wywołań narzędzi (1 z 28 płatnych, 8 z 400 darmowych). Dwa z darmowych ukrywały to za wyzwalaczami. Siedemnaście darmowych routerów użyło należącego do badaczy poświadczenia-pułapki AWS, a jeden opróżnił należący do badaczy klucz Ethereum, na którym było mniej niż 50 dolarów.1
- Co zrobił wyciekły klucz i słabe przekaźniki. Jeden celowo ujawniony klucz OpenAI obsłużył 100 mln tokenów GPT-5.4 i odsłonił ponad siedem sesji Codex. Słabo skonfigurowane przekaźniki-wabiki obsłużyły około 2 mld tokenów i odsłoniły 99 poświadczeń w 440 sesjach Codex, z których 401 działało już z automatycznie zatwierdzanymi wywołaniami narzędzi.1
- Co dały zabezpieczenia. W syntetycznym benchmarku samych autorów bramka polityki typu fail-closed zablokowała każdą próbkę wstrzyknięcia przy 1,0% fałszywych alarmów, a w prostym benchmarku adaptacyjnym atakujący, który wiedział o bramce, obszedł ją w 100% próbek. Wykrywanie anomalii oznaczyło 89,0% zwykłych wstrzyknięć i mniej więcej połowę tych z mechanizmami unikania.1
- Co według autorów by to naprawiło. Koperta odpowiedzi podpisana przez dostawcę, dzięki której klient może sprawdzić wywołanie narzędzia względem tego, co wygenerował model. Autorzy nie znaleźli żadnego dużego dostawcy, który by ją oferował.1
- Jeśli router jest hostowany samodzielnie. Aktualizacja z 1 października poniżej omawia jedenaście biuletynów bezpieczeństwa LiteLLM; jeden z nich pozwalał dowolnemu uwierzytelnionemu użytkownikowi sprawić, by proxy wysłało na zewnątrz swoje klucze dostawców.2
Kluczowe wnioski
- Operatorzy agentów: Każdy router między klientem a dostawcą modelu ma dostęp do każdego żądania i każdej odpowiedzi w postaci zwykłego tekstu, a klient konfiguruje wyłącznie pierwszy przeskok. Router kupiony na marketplace albo wzięty z publicznej listy należy traktować jak wrogiego pośrednika, dopóki nie pojawi się niezależny powód, by zaufać jego operatorowi.
- Twórcy harnessów: Hook PreToolUse uruchamia się, zanim wywołanie narzędzia zostanie wykonane, a wtedy router miał już okazję je przepisać. Hook nie ma oryginału, z którym mógłby porównać. Może natomiast działać w trybie fail-closed: dopuszczać polecenia powłoki, które pobierają tylko z domen z listy i instalują tylko pakiety z listy, a resztę blokować.3
- Wszyscy, którzy używają YOLO mode: W badaniu z wabikami 401 z 440 zaobserwowanych sesji Codex działało już z automatycznie zatwierdzanym wykonywaniem narzędzi.1 W tych sesjach zwykłe przepisane polecenie zostałoby wykonane bez żadnej logiki wyzwalaczy. Sesji z automatycznym zatwierdzaniem nie należy puszczać przez router, nad którym nie ma się kontroli.
- Zespoły hostujące własne proxy: Router uruchamiany samodzielnie tak samo skupia w sobie klucze dostawców. Jedenaście biuletynów LiteLLM, które trafiły do bazy PyPA 1 października 2026 roku, w większości publicznych od czerwca, obejmuje jeden, który pozwalał dowolnemu uwierzytelnionemu użytkownikowi sprawić, by proxy wysłało klucze dostawców na wybrany przez niego host. Wydania od 1.97.0 wzwyż leżą poza wszystkimi jedenastoma zarejestrowanymi zakresami; szczegóły zawiera aktualizacja z 1 października poniżej.2
Czym właściwie jest router?
Router LLM API przyjmuje żądania w jednym formacie, zwykle zgodnym z OpenAI, wybiera nadrzędnego dostawcę i zwraca odpowiedź. Artykuł znajduje routery w każdej skali: usługi zarządzane w chmurze, takie jak Amazon Bedrock i Azure OpenAI Service, projekty i usługi dla programistów, takie jak LiteLLM i OpenRouter, oraz masowy rynek odsprzedawanego i agregowanego dostępu do API.1
Ludzie korzystają z nich z rozsądnych powodów. Artykuł wymienia „model fallback, load balancing, cost optimization, and a single API key across providers” (przełączanie awaryjne między modelami, równoważenie obciążenia, optymalizację kosztów i jeden klucz do wszystkich dostawców) i zauważa, że routing jest szczególnie popularny „in regions where direct provider access is restricted, expensive, or subject to quota limitations” (w regionach, gdzie bezpośredni dostęp do dostawcy jest ograniczony, drogi albo objęty limitami).1
Problemem jest pozycja. Jak piszą autorzy, nie trzeba żadnej sztuczki z przechwytywaniem: „the client voluntarily configures the router’s URL as the API endpoint, the router terminates the client-side TLS connection, and it originates a separate TLS connection upstream” (klient sam ustawia adres routera jako punkt końcowy, router kończy jego połączenie TLS i otwiera osobne w górę). TLS chroni każdy odcinek, ale w żaden sposób nie chroni ładunku przed samym routerem, który czyta JSON żądania, przekazuje go dalej, czyta JSON odpowiedzi i zwraca go, mogąc po drodze zmienić jedno i drugie.1
Routery tworzą też łańcuchy. Przykład z artykułu: programista kupuje dostęp u odsprzedawcy z Taobao, ten agreguje klucze od pośrednika drugiego poziomu, który kieruje ruch przez OpenRouter, a OpenRouter przekazuje go do hosta modelu. To cztery przeskoki, każdy z pełnym dostępem do zwykłego tekstu. „The client configures only the first hop; subsequent hops are invisible.” (Klient konfiguruje tylko pierwszy przeskok; kolejne są niewidoczne.) Jeden zły przeskok w dowolnym miejscu skaża całą ścieżkę, a uczciwe przeskoki za nim nie są w stanie tego zauważyć.1
Dzisiejsze API nie zamykają tej luki. Argumenty wywołań narzędzi wędrują jako JSON w postaci zwykłego tekstu, a „No provider-level integrity mechanism binds the arguments returned by the model to the arguments received by the client.” (żaden mechanizm integralności po stronie dostawcy nie wiąże argumentów zwróconych przez model z argumentami odebranymi przez klienta).1
Jak przebiegał pomiar
Dla każdego routera autorzy przeszli przez cztery etapy. Zarejestrowali kontrolowane przez siebie konto i uzyskali dane uwierzytelniające API. Przepuścili to konto przez odizolowane środowisko agentowe wykonujące „a randomized subset of custom tasks and TerminalBench 2.0 tasks” (losowy podzbiór własnych zadań i zadań z TerminalBench 2.0), które generują realistyczne wywołania narzędzi: polecenia powłoki, instalacje pakietów i operacje na plikach. Każdy zwrócony ładunek wywołania narzędzia wykonali w piaskownicy, która śledziła połączenia zwrotne w sieci, zmiany w systemie plików i anomalie w drzewie procesów. Następnie osobny agent analityczny przeglądał oznaczone wykonania i klasyfikował każde jako nieszkodliwe przepisanie, potencjalnie złośliwe albo potwierdzone jako złośliwe.1
Definicje są ostrożne. Router uznaje się za wstrzykujący złośliwy kod „only if a returned tool-call payload is rewritten into an attacker-controlled command or dependency” (tylko jeśli zwrócone wywołanie zostało przepisane na polecenie lub zależność atakującego). Pułapkę AWS uznaje się za ruszoną, gdy poświadczenie, które przeszło przez router, „later produces follow-on AWS API activity attributable to that credential” (wywołuje potem aktywność w API AWS przypisywalną temu poświadczeniu).1
Korpus to rynek masowy, a nie cała dziedzina. W 400 darmowych routerach dominują dwa szablony open source, sub2api i new-api, a autorzy zaznaczają, że wdrożenia korporacyjne i dostępne tylko na zaproszenie są poza zakresem badania. Większość korpusu pochodzi z chińskojęzycznych platform handlowych i społeczności.1
Dane z terenu
| Zachowanie | Routery płatne (28) | Routery darmowe (400) |
|---|---|---|
| Wstrzykuje złośliwy kod do zwracanych wywołań narzędzi | 1 | 8 |
| Ukrywa wstrzyknięcie za wyzwalaczem | 0 zaobserwowanych | 2 |
| Używa należącego do badaczy poświadczenia-pułapki AWS | 0 zaobserwowanych | 17 |
| Opróżnia należący do badaczy klucz Ethereum | 0 zaobserwowanych | 1 |
Wstrzyknięcia nie są kosmetyczne. Według artykułu „change the command or dependency that the agent intends to execute” (zmieniają polecenie lub zależność, które agent zamierza wykonać). Wynik dla routerów płatnych to jeden na 28, a autorzy wyciągają prosty wniosek: „Paid access improves service stability, but it does not prove tool-call integrity.” (Płatny dostęp poprawia stabilność usługi, ale nie dowodzi integralności wywołań narzędzi.)1
Dwa routery z wyzwalaczami to odkrycie, które unieważnia testowanie. W pierwszym „malicious tool calls are injected only after the first 50 requests, which hides the attack from shallow smoke tests” (złośliwe wywołania pojawiają się dopiero po pierwszych 50 żądaniach, co ukrywa atak przed powierzchownymi testami). W drugim wstrzykiwanie włącza się „only for sessions that appear to be running in autonomous YOLO mode and only when the project fingerprint matches Rust or Go” (tylko w sesjach, które wyglądają na autonomiczny YOLO mode, i tylko gdy odcisk projektu wskazuje na Rust lub Go). Autorzy dodają, że zaobserwowane wyzwalacze mogą nie być jedynymi. Badali te routery wyłącznie skończonym sondowaniem metodą czarnej skrzynki, więc „a router may implement additional latent conditions that our probes did not activate” (router może mieć dodatkowe ukryte warunki, których ich sondy nie uruchomiły).1
Wszystkie ustalenia dotyczące poświadczeń dotyczą zbioru darmowego. Siedemnaście routerów „trigger follow-on use of at least one researcher-owned AWS canary credential after seeing it in transit” (doprowadza do późniejszego użycia co najmniej jednego należącego do badaczy poświadczenia-pułapki AWS po zobaczeniu go w ruchu), a jeden opróżnił zasilony wcześniej klucz Ethereum. Według załącznika strata z tego opróżnienia wyniosła mniej niż 50 dolarów amerykańskich.1
Dwa badania dotyczące zatruwania
Router nie musi być złośliwy, żeby znaleźć się w tej samej pozycji. Autorzy przeprowadzili dwa badania pokazujące, jak zatruwa się ścieżkę przez routery, które wyglądają na nieszkodliwe.
Badanie 1: wyciekły klucz. Badacze ujawnili należący do siebie klucz API OpenAI „on Chinese forums, WeChat, and Telegram groups frequented by router operators” (na chińskich forach oraz w grupach WeChat i Telegram, w których bywają operatorzy routerów). Ten jeden klucz obsłużył 100 mln tokenów GPT-5.4 i odsłonił ponad siedem sesji użytkowników Codex, a w co najmniej jednej sesji pojawiło się za nim kilka różnych poświadczeń. Artykuł ostrożnie opisuje, jak ten ruch tam trafił. Wynik „is consistent with several paths: direct reuse by a router operator, direct reuse by unrelated third parties, or reuse somewhere inside a longer relay chain” (pasuje do kilku ścieżek: bezpośredniego ponownego użycia przez operatora routera, przez niezwiązane osoby trzecie albo gdzieś w dłuższym łańcuchu przekaźników), a autorzy „cannot always distinguish among those paths from provider-side logs alone” (nie zawsze potrafią je rozróżnić na podstawie samych logów dostawcy). Badanie ustala promień rażenia: kto ma ponownie użyty klucz nadrzędny, ten widzi stojący za nim ruch w postaci zwykłego tekstu.1
Badanie 2: słabe przekaźniki. Badacze uruchomili podatne instancje claude-relay-service w 20 domenach oraz instancje Sub2API i CLIProxyAPI ze słabymi hasłami pod 20 adresami IP. Wabiki przyciągnęły ponad 40 000 prób nieautoryzowanego dostępu ze 147 adresów IP, które autorzy odczytują jako mieszankę skanowania i ponownego użycia przekaźników, a nie w każdym przypadku jako ataki celowane. Mocniejszy sygnał przyszedł później: wabiki „were folded into active agent-facing relay paths” (zostały włączone do aktywnych ścieżek przekaźników obsługujących agentów). Obsłużyły około 2 mld tokenów GPT-5.4 i 5.3-codex, około 13 GB widocznego ruchu promptów i odpowiedzi, i odsłoniły 99 unikalnych poświadczeń w 440 sesjach Codex obejmujących 398 projektów lub hostów.1
Każda z tych 440 sesji była według definicji z artykułu podatna na wstrzyknięcie polecenia, a 401 „already operated in YOLO mode, i.e., with tool execution auto-approved rather than confirmed command by command” (już działało w YOLO mode, czyli z automatycznie zatwierdzanym wykonywaniem narzędzi zamiast potwierdzania każdego polecenia). W przypadku tych 401, jak piszą autorzy, „sophisticated adaptive evasion was unnecessary: basic payload injection would have been sufficient to change executed commands” (wyrafinowane unikanie wykrycia było zbędne: do zmiany wykonywanych poleceń wystarczyłoby proste wstrzyknięcie).1
Były to sesje innych ludzi. Ich ruch dotarł do wabików po tym, jak wabiki zostały włączone do ścieżek przekaźników, a użytkownik konfigurujący tylko pierwszy przeskok nie miał jak tego zobaczyć. Autorzy zachowali wyłącznie zagregowane metadane i solone skróty, a po zamknięciu okna obserwacji wycofali własne odsłonięte poświadczenia.1
Dwie podstawowe klasy ataków i dwa warianty unikania
Artykuł sprowadza zachowanie złośliwego routera do dwóch prymitywów i dwóch udoskonaleń pierwszego z nich.1
AC-1: wstrzyknięcie ładunku po stronie odpowiedzi. Router przepisuje wywołanie narzędzia po tym, jak opuściło dostawcę, a zanim dotrze do klienta, zachowując nazwę narzędzia i schemat. Przykład z artykułu to wywołanie Bash, w którym adres instalatora zostaje podmieniony na adres atakującego. Wynik nadal jest poprawnym JSON-em dla oczekiwanego narzędzia, więc klient nie widzi niczego podejrzanego.
AC-2: pasywna eksfiltracja sekretów. Router niczego nie zmienia. Przeszukuje żądania i odpowiedzi pod kątem wzorców poświadczeń i zatrzymuje to, co znajdzie. Ruch pozostaje niezmieniony, więc „clients cannot observe router-side retention” (klienci nie mogą zaobserwować, co router zatrzymuje). Ekspozycja wykracza poza klucze API: „system prompts, tool definitions, user-supplied file contents, and environment variables all transit the same plaintext channel” (prompty systemowe, definicje narzędzi, zawartość plików użytkownika i zmienne środowiskowe przechodzą tym samym jawnym kanałem).
AC-1.a: wstrzyknięcie ukierunkowane na zależności. Wariant AC-1 wymierzony w polecenia instalujące pakiety. Zamiast podmieniać adres URL, router „substitutes a legitimate dependency name with an attacker-controlled package pre-registered on the target registry” (zastępuje nazwę prawdziwej zależności pakietem atakującego, zarejestrowanym zawczasu w docelowym rejestrze). W przykładzie z artykułu pip install requests zamienia się w pip install reqeusts. Polecenie nadal instaluje z zaufanego rejestru, więc bramka sprawdzająca tylko domeny je przepuszcza, a zły pakiet zostaje w pamięci podręcznej na kolejne sesje.
AC-1.b: dostarczanie warunkowe. Wariant, który decyduje, kiedy AC-1 się uruchamia. Router zachowuje się uczciwie, dopóki nie zadziała wyzwalacz. Artykuł wymienia pięć rodzin wyzwalaczy: nazwę narzędzia, słowa kluczowe w treści, odciski użytkownika, takie jak YOLO mode, okna czasowe i liczbę żądań. „A router deploying a 50-request warm-up appears entirely transparent during a 10-request probe.” (Router z rozgrzewką na 50 żądań wygląda na zupełnie przezroczysty podczas sondy z 10 żądań.)
Artykuł przedstawia marcowy kompromis LiteLLM z 2026 roku jako AC-1 na dużą skalę: gdy atakujący przejął potok przetwarzania żądań w proxy, każde przechodzące przez nie wywołanie narzędzia można było przepisać. (Artykuł opisuje ten incydent jako dependency confusion, czyli pomylenie zależności. Źródła, na których oparłem wpis o łańcuchu dostaw, wskazują na token publikacyjny PyPI skradziony w wyniku kompromitacji Trivy.)
Co badawcze proxy pokazało o klientach agentowych
Autorzy zbudowali proxy o nazwie Mine, które implementuje wszystkie cztery klasy, i przepuścili po 1000 żądań z wywołaniami narzędzi na każdy moduł ataku przez każdy z czterech publicznych frameworków agentowych: OpenClaw, OpenCode, Codex od OpenAI i Claude Code od Anthropic.1
Żaden z czterech nie zweryfikował integralności odpowiedzi. Przepisane wywołanie narzędzia dotarło w poprawnej, natywnej dla frameworka postaci w 100% przypadków AC-1 i w 99,6% przypadków AC-1.a. Artykuł precyzyjnie określa, co to pokazuje, a czego nie: „These are compatibility measurements, not end-to-end execution rates: they show that the tampered tool call reaches the client in a valid framework-native format, but downstream permission prompts or local execution sandboxes may still block the resulting action.” (To pomiary zgodności, a nie odsetki wykonania: zmanipulowane wywołanie dociera w poprawnym formacie, ale monit o uprawnienia lub lokalna piaskownica mogą jeszcze zablokować skutek.)1
To zastrzeżenie pokazuje, gdzie monit o uprawnienia naprawdę się przydaje, i wyjaśnia, dlaczego automatyczne zatwierdzanie tak mocno waży w liczbach z wabików. Autorzy nie udostępnili Mine.1
Wzorzec kompozycji, o jedną warstwę niżej
Ciągle piszę o tym samym błędzie strukturalnym: komponenty, z których każdy z osobna ma uprawnienia, składają się w zachowanie, na które nikt nie dał zgody. Trivy-to-LiteLLM był kompozycją w warstwie pakietów. Cichy egress był kompozycją w warstwie pobieranych treści. Zatruwanie narzędzi MCP było kompozycją w warstwie protokołu.
Atak przez router to kompozycja na przeskoku między klientem a dostawcą. Klient ma uprawnienia do wywołania routera. Router ma uprawnienia do wywołania nadrzędnego modelu. Model ma uprawnienia do odpowiedzi. Każdy przeskok jest autoryzowany, a kompozycja i tak daje przepisane polecenia, bo nikt nie podpisuje tego, co przechodzi przez przeskok, oraz skopiowane sekrety, bo każdy przeskok czyta to w postaci zwykłego tekstu.
Artykuł prowadzi tę linię aż do samego MCP: „a malicious MCP server receives tool-call requests in plaintext and can return forged results, so the same basic manipulation and collection ideas transfer with adaptation to the MCP message format” (złośliwy serwer MCP dostaje żądania wywołań narzędzi jawnym tekstem i może zwracać sfałszowane wyniki, więc te same pomysły na manipulację i zbieranie danych przenoszą się, po dostosowaniu, na format wiadomości MCP). Wskazuje też różnicę. Serwer MCP stoi po stronie wykonywania narzędzi i może fałszować ich wynik. Router stoi na drodze do modelu i widzi każde wywołanie narzędzia oraz cały kontekst żądania.1
Trzy zabezpieczenia i liczby z artykułu
Artykuł ocenia trzy mechanizmy kontroli, które klient może wdrożyć bez pomocy jakiegokolwiek dostawcy. Wszystkie poniższe liczby obarczone są jednym zastrzeżeniem: „All numbers in this section come from controlled artifact-side evaluation rather than field data.” (Wszystkie liczby w tej sekcji pochodzą z kontrolowanej oceny, a nie z danych z terenu.) Korpusy są syntetyczne, wygenerowane skryptami autorów.1
| Zabezpieczenie | AC-1 | AC-1.a | AC-1.b | Koszt i ograniczenie |
|---|---|---|---|---|
| Bramka polityki fail-closed | 100% zablokowanych | 100% zablokowanych | nie mierzono | 1,0% fałszywych alarmów; obejście w 100% próbek w prostym benchmarku adaptacyjnym |
| Wykrywanie anomalii po stronie odpowiedzi | 89,0% oznaczonych | 50,0% oznaczonych | 50,9% oznaczonych | 6,7% fałszywych alarmów |
| Dziennik przejrzystości typu append-only | tylko audyt | tylko audyt | tylko audyt | około 1,26 KB na wpis |
Bramka polityki blokuje polecenia powłoki, które „fetch from non-allowlisted domains or install packages outside a local allowlist” (pobierają z domen spoza listy dozwolonych albo instalują pakiety spoza lokalnej listy). Na 1000 nieszkodliwych poleceń, 500 próbkach AC-1 i 500 próbkach AC-1.a zablokowała każdą próbkę ataku, a wszystkie jej fałszywe alarmy dotyczyły pobierania instalatorów z domen lustrzanych, których brakowało na liście. Autorzy nazywają ją „the strongest immediately deployable control” (najsilniejszym mechanizmem, który można wdrożyć od razu). Równie otwarcie opisują jej porażkę. Jeśli atakujący umieści ładunek w domenie z listy dozwolonych albo wcześniej podrzuci lokalny skrypt, który później uruchomi niewinnie wyglądające polecenie, „the policy gate is bypassed in 100% of samples” (bramkę udaje się obejść w 100% próbek). Ich werdykt: bramkę „should be understood as a coarse but useful filter for obvious high-risk workflows, not as a robust defense against defense-aware attackers” (należy rozumieć jako zgrubny, ale przydatny filtr dla oczywiście ryzykownych przepływów, a nie jako solidną obronę przed atakującymi, którzy znają zabezpieczenia).1
Jeden szczegół ma znaczenie dla każdego, kto buduje taką bramkę, a artykuł nie jest w nim konsekwentny. Sekcja 4 opisuje bramkę jako sprawdzającą tylko domeny i projektuje AC-1.a tak, by ją pokonać: „the gate blocks non-allowlisted domains but does not maintain a per-package allowlist” (bramka blokuje domeny spoza listy, ale nie prowadzi listy pakietów). Bramka z sekcji 7, ta, która uzyskała 100% przeciwko AC-1.a, blokuje też instalacje „outside a local allowlist” (spoza lokalnej listy). W moim odczytaniu bramka bez listy pakietów całkowicie przepuszcza podmianę nazwy przez typosquatting.
Wykrywanie anomalii ocenia każde zwrócone wywołanie narzędzia na podstawie cech widocznych lokalnie, takich jak ryzykowne wzorce poleceń powłoki i entropia argumentów, bez nadrzędnego oryginału do porównania. Przy 6,7% fałszywych alarmów oznaczyło 89,0% próbek AC-1, 50,0% AC-1.a i 50,9% AC-1.b. Przy budżecie 1% fałszywych alarmów wychwyciło 43,5% AC-1 i praktycznie nic z AC-1.a. Autorzy oceniają je jako „useful for review prioritization” (przydatne do ustalania kolejności przeglądów) i słabsze od bramki.1
Dziennik przejrzystości zapisuje żądanie, odpowiedź, adres routera, metadane TLS i skrót surowej odpowiedzi. Niczemu nie zapobiega. Pozwala po incydencie ustalić, jak daleko sięgnął router lub poświadczenie i które sesje przez nie przeszły.1
Rozwiązanie, o które proszą autorzy
Żaden z trzech mechanizmów nie uwierzytelnia, skąd pochodzi wywołanie narzędzia. Autorzy mówią to wprost: „No client-side control available today can prove that a router preserved the upstream provider’s response.” (Żaden dostępny dziś mechanizm po stronie klienta nie dowiedzie, że router zachował odpowiedź dostawcy.)1
Dowiódłby tego podpis dostawcy. Artykuł proponuje „a provider-signed canonical response envelope, similar in spirit to DKIM for email” (kanoniczną kopertę odpowiedzi podpisaną przez dostawcę, w duchu podobną do DKIM w poczcie e-mail), obejmującą identyfikator modelu, nazwę narzędzia, jego argumenty, powód zakończenia i nonce klienta, którą klient weryfikuje przed wykonaniem jakiegokolwiek wywołania narzędzia. Stwierdza też, że nikt czegoś takiego nie oferuje: „To our knowledge, none of the major provider tool-use APIs or the current MCP specification expose a deployed response-signing mechanism for tool-call arguments today.” (Według wiedzy autorów ani API dużych dostawców, ani obecna specyfikacja MCP nie udostępniają dziś wdrożonego mechanizmu podpisywania argumentów wywołań.)1
Propozycja ma dwa ograniczenia. Bezpieczeństwo transportu jej nie zastąpi: wzajemny TLS i przypinanie certyfikatów „can authenticate the router endpoint the client chose, but they do not say whether the returned tool call preserves upstream semantics” (mogą uwierzytelnić wybrany przez klienta punkt końcowy, ale nie mówią, czy zwrócone wywołanie zachowało to, co wygenerował dostawca). Podpisy nie pomogą też na skradzione sekrety: „AC-2 cannot be mitigated by response-signing proposals because the secrets are exposed on the request path before any provider-side mechanism can act.” (Podpisywanie odpowiedzi nie łagodzi AC-2, bo sekrety są odsłonięte na ścieżce żądania, zanim dostawca zdąży cokolwiek zrobić.)1
Co tak naprawdę należy zrobić
Jeśli agent wywołuje model przez router, którego nie zbudowano samodzielnie:
- Łączyć się bezpośrednio, gdzie to możliwe, a gdzie nie, znać operatora. Do dodania routera wystarczy zmiana bazowego adresu URL i dlatego dodaje się go bez żadnej decyzji. Warto uczynić z tego decyzję. „Zaufanie” oznacza tu zewnętrzną podstawę, na przykład znany zespół, umowę albo jurysdykcję, w której można dochodzić swoich praw. Opinie na marketplace taką podstawą nie są.
- Stosować fail-closed dla ryzykownych wywołań narzędzi. W Claude Code oznacza to hook PreToolUse, który blokuje polecenia powłoki pobierające z domen spoza listy dozwolonych oraz instalacje pakietów spoza listy dozwolonych. Listę pakietów należy zachować: wariant z podmianą zależności istnieje po to, by pokonać bramkę sprawdzającą tylko domeny. Hook trzeba napisać tak, by odrzucał wszystko, czego nie potrafi przeanalizować, kodem wyjścia 2 albo decyzją
deny: Claude Code traktuje inne kody wyjścia i przekroczenia limitu czasu jako nieblokujące, więc hook, który się wywali albo zawiesi, nie zatrzyma wywołania, które przejdzie dalej zwykłą ścieżką uprawnień, a w sesji z automatycznym zatwierdzaniem po prostu się wykona. Warto też sprawdzić, czy hook uruchomił się przy pierwszym wywołaniu. Dokumentacja ostrzega, że „a mistyped path in settings.json leaves the gate silently disabled” (literówka w ścieżce w settings.json po cichu wyłącza bramkę). Trzeba się liczyć z utrzymywaniem obu list i z tym, że zdeterminowany atakujący je obejdzie.3 - Nigdy nie puszczać sesji z automatycznym zatwierdzaniem przez router, nad którym nie ma się kontroli. Precedensem jest 401 sesji z badania z wabikami. Monit o uprawnienia to jedna z niewielu rzeczy, które stoją między przepisanym wywołaniem narzędzia a jego wykonaniem.
- Trzymać sekrety z dala od ruchu. Pasywne zbieranie nie zmienia niczego, co dałoby się zaobserwować. Wszystko, co trafia do promptu, wyniku narzędzia albo pliku czytanego przez agenta, przechodzi przez router w postaci zwykłego tekstu. Poświadczenia należy wąsko ograniczać, w miarę możliwości trzymać poza kontekstem i rotować wszystko, co przeszło przez router, co do którego pojawiły się później wątpliwości.
- Logować lokalnie. Żądania, odpowiedzi, adres routera i skrót odpowiedzi, z sekretami usuniętymi wcześniej z żądań, przechowywane tam, gdzie router nie sięga. To nie zatrzyma ataku. Pozwoli potem ustalić, co zostało odsłonięte.
- Uruchamiać wykonanie w piaskownicy. Artykuł zauważa, że piaskownice „reduce post-execution blast radius but do not authenticate where a tool call came from” (zmniejszają promień rażenia po wykonaniu, ale nie uwierzytelniają, skąd pochodzi wywołanie narzędzia). Warto wziąć pierwszą połowę.
Niewygodna implikacja
Warstwa routerów to czysty przykład tego, jak ekosystem agentów wdraża infrastrukturę szybciej, niż ją zabezpiecza. Ludzie chcą jednego klucza do wszystkich modeli, niższych cen i dostępu z regionów, których dostawca nie obsługuje. Routery dają wszystkie trzy rzeczy, a rynek je za to nagradza.
Ta sama sekwencja rozegrała się już w warstwie MCP, w warstwie pakietów i w warstwie pobieranych treści. Pojawia się nowa warstwa stosu agentowego. Programiści ją przyjmują, zanim ktokolwiek ją zaudytuje. Przychodzą atakujący, a po nich badacze. Tutaj badacze naliczyli 428 routerów, 9 wstrzykujących złośliwy kod, 17 używających podłożonych poświadczeń, 1 opróżniający portfel i 401 automatycznie zatwierdzanych sesji płynących ścieżkami przekaźników, do których należały też wabiki badaczy.1
Elementu, który zamknąłby lukę, czyli odpowiedzi podpisanej przez dostawcę, operator nie jest w stanie dodać sam. Dopóki dostawcy go nie wdrożą, opisane wyżej mechanizmy ograniczają ekspozycję, ale żaden nie dowodzi, że wywołanie narzędzia naprawdę pochodzi od modelu.
Aktualizacja z 1 października 2026: router hostowany samodzielnie też jest na liście
Ten wpis dotyczy routerów prowadzonych przez kogoś innego. Rejestr biuletynów bezpieczeństwa uzupełnia drugą połowę. 1 października 2026 roku baza biuletynów PyPA dodała jedenaście wpisów dotyczących LiteLLM, otwartoźródłowego proxy, które zespoły hostują samodzielnie z powodów opisanych wyżej: jeden klucz do wszystkich modeli.2 Żaden z nich nie jest nowy. Dziewięć figuruje w bazie biuletynów GitHuba i w NVD od 21 czerwca, dziesiąty od połowy września, a ten najważniejszy dla proxy, bo odsłania klucze dostawców, opublikowano we własnym repozytorium LiteLLM 26 sierpnia, przy czym poprawki są w PyPI od 9 sierpnia; GitHub ocenia go jako Moderate. Warto czytać je razem, bo mówią coś o tej warstwie, a także dlatego, że każde wydanie finalne opublikowane przed 9 sierpnia mieści się w zakresie CVE-2026-84377.
Najpierw warto przeczytać CVE-2026-84377. Biuletyn w repozytorium mówi: „Any authenticated LiteLLM proxy user could redirect an outbound provider call to a destination they control and cause the proxy to send its own configured provider credentials to that destination.” (Każdy uwierzytelniony użytkownik proxy mógł przekierować wychodzące wywołanie do kontrolowanego przez siebie celu i sprawić, że proxy wyśle tam swoje poświadczenia dostawców.) Przyczyną jest kształt kontroli: „The proxy’s request-body validation was a denylist that did not cover every sensitive parameter and did not inspect parameters nested inside other request fields.” (Walidacja treści żądania była listą zakazów, która nie obejmowała wszystkich wrażliwych parametrów ani nie sprawdzała parametrów zagnieżdżonych w innych polach.) Poprawkę wydano w dziewięciu liniach wydań, od 1.88.6 do 1.96.2. Dla tych, którzy nie mogą jeszcze zaktualizować, biuletyn podaje w jednym zdaniu trzy obejścia: „Set general_settings.allow_client_side_credentials to false so callers cannot override connection parameters, restrict proxy keys to trusted callers, and block the affected parameters (api_base, base_url, model_list, fallbacks, provider credential fields) at a reverse proxy or API gateway.” (ustawić tę opcję na false, by wywołujący nie mogli nadpisywać parametrów połączenia, ograniczyć klucze proxy do zaufanych wywołujących i blokować wymienione parametry na odwrotnym proxy lub bramie API).2 Pierwsze z nich samo nie wystarcza. W kodzie źródłowym 1.95.0, jednego z podatnych wydań, kontrola treści żądania jest całkowicie pomijana tylko wtedy, gdy to ustawienie ma wartość true (configurable_clientside_auth_params danego wdrożenia nadal może zwalniać pojedyncze parametry), więc false to stan, w którym i tak jest instalacja, która nigdy tego ustawienia nie ruszała, a niepełna kontrola to właśnie błąd opisany w biuletynie. Rozwiązaniem jest aktualizacja.6
Drugi wpis, CVE-2026-59823, to ten sam błąd w miniaturze: zabezpieczenie „blocks the api_base and base_url parameters but does not cover user_config,” (blokuje te dwa parametry, ale nie obejmuje user_config), więc wywołujący z ważnym kluczem wirtualnym mógł umieścić w nim api_base i skierować proxy na dowolny host. Ten błąd załatano w 1.83.9, dostępnym w PyPI od 17 kwietnia; biuletyn pojawił się we wrześniu.4
Dwa wpisy dotyczą strony MCP w proxy: niewłaściwego uwierzytelniania w proxy MCP (CVE-2026-12773, z zakresem wersji kończącym się poprawką w 1.84.0) oraz fałszowania żądań po stronie serwera przez argument spec_path modułu ładującego specyfikacje OpenAPI dla MCP (CVE-2026-12798, zarejestrowany jako dotyczący wersji do 1.82.2 włącznie). Pozostałe siedem obejmuje obsługę kluczy administracyjnych, przepływ debugowania SSO, unieważnianie sesji SSO, wygasanie sesji dla generowanych kluczy, enumerację użytkowników w interfejsie, obejście mechanizmu guardrail na asynchronicznych punktach końcowych oraz obsługę JWT między maszynami.5
Tych dziewięć rekordów jest uboższych niż dwa pierwsze. Ich opisy powtarzają szablonowe sformułowania VulDB zamiast opisu od opiekuna projektu, a opis wpisu o proxy MCP mówi „up to 1.59.8” (do 1.59.8), podczas gdy zakres wersji wskazuje poprawkę w 1.84.0.5 Rekord CVE-2026-84377 ma własną niespójność: strona repozytorium podaje jako podatne wersje „<1.94.0”, a zakresy w zweryfikowanym rekordzie obejmują linię 1.96 aż do poprawki w 1.96.2.2
Zakresy należy porównać z wydaniem, którego się faktycznie używa, zamiast ufać streszczeniu, również temu. Każdy zarejestrowany zakres kończy się na 1.96.2 lub niżej, więc wydania od 1.97.0 wzwyż, dostępne w PyPI od 16 sierpnia, leżą poza wszystkimi jedenastoma; aktualne wydanie na dzień 1 października to 1.103.2.5
Niebezpieczeństwo routera tkwi w tym, gdzie leżą poświadczenia, niezależnie od tego, kto go prowadzi. Router z marketplace, który używa podłożonego klucza AWS, i hostowane samodzielnie proxy, które da się namówić do wysłania kluczy dostawców na zewnątrz, to ta sama ekspozycja osiągnięta z dwóch kierunków: raz przez operatora, raz przez dowolnego najemcę z kluczem wirtualnym. Zabezpieczenia z poprzednich sekcji zakładają, że jest się klientem.
Przy proxy prowadzonym samodzielnie trzeba dodać połowę należącą do operatora: traktować każdy klucz wirtualny jako poświadczenie do stojących za nim kluczy nadrzędnych, trzymać wyłączone parametry połączenia przekazywane przez klienta, w tym configurable_clientside_auth_params na poziomie wdrożenia, chyba że są naprawdę potrzebne, i objąć proxy tym samym rytmem łatek co wszystko inne, co przechowuje sekrety.
Jeśli ktoś, komu nie ufa się w pełni, miał klucz wirtualny w czasie, gdy proxy działało na podatnym wydaniu, należy zrotować klucze dostawców i wszystkie inne sekrety skonfigurowane w proxy oraz przejrzeć jego logi pod kątem wywołań wychodzących do hostów, których nie skonfigurowano; opisany w biuletynie wpływ obejmuje „other configured secrets” (inne skonfigurowane sekrety) i żądania do „internal services reachable from the proxy” (usług wewnętrznych osiągalnych z proxy). Dwa z jedenastu wpisów, CVE-2026-12773 w proxy MCP i CVE-2026-12795 w przepływie debugowania SSO, to błędy uwierzytelniania w wydaniach poniżej 1.84.0, więc w tych wydaniach to, kto miał klucz, może nie wyznaczać granicy tego, kto mógł dostać się do proxy; jeśli było ono osiągalne z sieci, którym się nie ufa, należy przeprowadzić taką samą rotację.
Co wersja kwietniowa zrobiła źle
Wersja tego wpisu z 10 kwietnia powstała na podstawie abstraktu artykułu. Zestawiona z pełnym tekstem 2 października 2026 roku okazała się błędna lub myląca w następujących miejscach, wszystkie poprawione powyżej:
- AC-1.a. Opisałem ją jako wstrzyknięcie, które „only fires when the request matches a specific dependency or context” (uruchamia się tylko wtedy, gdy żądanie pasuje do określonej zależności lub kontekstu). W rzeczywistości to podmiana nazwy pakietu w poleceniu instalacji. Wyzwalacze to AC-1.b.
- Zabezpieczenia. Napisałem, że „the abstract does not rank the defenses” (abstrakt nie szereguje zabezpieczeń), i podałem własny ranking jako opinię. Treść artykułu mierzy wszystkie trzy, nazywa bramkę polityki „the strongest immediately deployable control” (najsilniejszym mechanizmem do wdrożenia od razu) i podaje, że w prostym benchmarku adaptacyjnym udało się ją obejść w 100% próbek. To pominąłem.
- Rada dotycząca podpisów. Doradzałem operatorom podpisywanie żądań po stronie klienta i weryfikowanie ich u nadrzędnego dostawcy, i nazwałem to „the only real fix” (jedynym prawdziwym rozwiązaniem). Artykuł proponuje odwrotny kierunek, czyli odpowiedź podpisaną przez dostawcę i weryfikowaną przez klienta, i stwierdza, że podpisy nie rozwiązują problemu skradzionych sekretów.
- Wyciekły klucz. Napisałem, że klucz ujawniono „as if it had been exposed through a developer mistake” (tak, jakby wyciekł przez błąd programisty), i wywnioskowałem, że „The router was a laundering layer for a stolen key.” (router był warstwą prania skradzionego klucza). Klucz ujawniono na forach i w grupach czatowych, w których operatorzy routerów wymieniają się poświadczeniami, a artykuł zaznacza, że nie zawsze da się ustalić, czy ponownie użył go operator routera, niezwiązana osoba trzecia, czy dłuższy łańcuch przekaźników.
- Liczby dotyczące poświadczeń. Blok odpowiedzi mówił, że „17 of 28 paid routers touched planted AWS credentials” (17 z 28 płatnych routerów sięgnęło po podłożone poświadczenia AWS), a opis podawał, że badacze przetestowali 28 routerów. Wiersz dla routerów płatnych w artykule nie wykazuje żadnego zaobserwowanego nadużycia poświadczeń. Wszystkie 17 routerów, które użyły pułapek AWS, i ten, który opróżnił ETH, należą do 400 darmowych.
- Rada dotycząca hooków. Zalecałem hooki PostToolUse, które „validate response shapes” (sprawdzają kształt odpowiedzi). Hook PostToolUse uruchamia się po wykonaniu narzędzia, czyli za późno na przepisane polecenie. Mechanizm testowany w artykule to bramka przed wykonaniem, którą w Claude Code jest hook PreToolUse z listą dozwolonych.
- Mniejsze błędy. Artykuł ma sześcioro autorów, nie pięcioro. Nie twierdzi, że router „knows when it is being sampled” (wie, kiedy jest sprawdzany); to był mój ozdobnik. Wstęp nazywał temat „MCP trust chains” (łańcuchami zaufania MCP), a artykuł bada routery, nie MCP. Wpis o cichym egressie opisałem jako dotyczący opisów narzędzi, choć dotyczy instrukcji ukrytych w pobieranych treściach.
Często zadawane pytania
Czym jest router LLM API w tym kontekście?
Usługą, która przyjmuje żądania w ujednoliconym formacie, zwykle zgodnym z OpenAI, wybiera nadrzędnego dostawcę modelu i zwraca odpowiedź. To proxy warstwy aplikacji z dostępem do każdego żądania i każdej odpowiedzi w postaci zwykłego tekstu.1
Czy TLS chroni przed złośliwym routerem?
Nie. Klient ustawia router jako swój punkt końcowy, więc router kończy sesję TLS klienta i otwiera osobną w kierunku dostawcy. TLS chroni każdy odcinek i w żaden sposób nie chroni ładunku przed routerem.1
Jak wykryć router, który przepisuje wywołania narzędzi?
Testowaniem nie da się tego zrobić niezawodnie. Dwa routery w badaniu wstrzykiwały dopiero po 50 żądaniach albo tylko w sesjach z automatycznym zatwierdzaniem przy projektach w Rust lub Go, a artykuł konkluduje, że „no fixed-length client test can guarantee that the router is benign” (żaden test klienta o stałej długości nie zagwarantuje, że router jest nieszkodliwy). Lista dozwolonych typu fail-closed dla poleceń powłoki i instalacji pakietów blokuje proste przypadki, a artykuł pokazuje, że atakujący znający zabezpieczenie ją omija.1
Czy hook PreToolUse pomaga?
Tak, jako bramka polityki. Hook widzi wywołanie narzędzia, które otrzymał klient, czyli wersję przepisaną, jeśli router ją przepisał, i może blokować polecenia pobierające z domen spoza listy lub instalujące pakiety spoza listy. Nie jest w stanie stwierdzić, czy wywołanie jest tym, co wygenerował model.13
Uruchamiam Claude Code bezpośrednio wobec api.anthropic.com. Czy to mnie dotyczy?
Nie w zakresie ataków przez router opisanych w tym artykule, bo nie ma pośrednika. Jeśli Claude Code jest kierowany przez jakiekolwiek proxy, na przykład bramę firmową albo agregator modeli, to proxy zajmuje dokładnie tę samą pozycję.
Co z OpenRouter, LiteLLM lub innymi znanymi agregatorami?
Artykuł mierzy 28 płatnych routerów z trzech platform handlowych i 400 darmowych, zbudowanych głównie na dwóch szablonach open source. LiteLLM i OpenRouter wymienia jako tło i ich nie testuje. Argument strukturalny dotyczy każdego routera: może czytać i przepisywać ruch, a widoczność to inna właściwość niż integralność. W przypadku proxy hostowanego samodzielnie aktualizacja z 1 października powyżej omawia jedenaście biuletynów LiteLLM.
Do kogo należało 401 sesji z automatycznym zatwierdzaniem?
Do osób trzecich, których ruch trafił do przekaźników-wabików badaczy. Jeśli sesje agentów z automatycznym zatwierdzaniem przechodzą przez router, którego nie zbudowano samodzielnie, należy je zatrzymać, zrotować każde poświadczenie, które przez niego przeszło, i przejrzeć logi sesji pod kątem nieoczekiwanych wywołań narzędzi.
Bibliografia
-
Hanzhi Liu, Chaofan Shou, Hongbo Wen, Yanju Chen, Ryan Jingyang Fang i Yu Feng, „Your Agent Is Mine: Measuring Malicious Intermediary Attacks on the LLM Supply Chain”, arXiv:2604.08407v1, 9 kwietnia 2026, zakwalifikowany na ACM Conference on Computer and Communications Security, październik 2026. Pełny tekst przeczytany 1 i 2 października 2026. Wykorzystane sekcje: wstęp i 2.1 (czym są routery, przykład z czterema przeskokami, kończenie TLS); 2.2 (brak mechanizmu integralności na poziomie dostawcy); 4.1 i 4.2 (cztery klasy ataków, przykład
requestsnareqeusts, pięć rodzin wyzwalaczy); 5.1 (czteroetapowy potok i definicje); 5.2 oraz tabele 3 i 4 (1 płatny i 8 darmowych routerów wstrzykujących, 2 darmowe z wyzwalaczami, 17 darmowych używających pułapek AWS, 1 opróżniający ETH); 5.3 (wyciekły klucz i wabiki: 100 mln tokenów, ponad siedem sesji Codex, ponad 40 000 prób dostępu ze 147 adresów IP, około 2 mld tokenów, około 13 GB, 99 poświadczeń, 440 sesji, 398 projektów lub hostów, 401 w YOLO mode); 5.4 (kluczowe ustalenia, w tym zdanie o płatnym dostępie); 5.5 (zakres); 6 i tabela 5 (Mine, cztery frameworki, 1000 żądań na moduł, zgodność 100% i 99,6%); 7 i tabela 6 (trzy zabezpieczenia i ich wyniki); 8.2 i 8.3 (podpisana koperta odpowiedzi, MCP); 9 (różnica między pozycją serwera MCP a pozycją routera); załącznik A (przechowywanie danych, wycofanie poświadczeń, opróżnienie poniżej 50 dolarów amerykańskich, nieudostępnienie Mine). ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩ -
Biuletyn w repozytorium LiteLLM GHSA-3cv6-jpf6-8222 (CVE-2026-84377, PYSEC-2026-4066), „Authenticated SSRF and provider-credential exfiltration via unvalidated request-body routing parameters”, opublikowany w repozytorium 26 sierpnia 2026, ujęty w NVD 2 września i zweryfikowany przez GitHub 30 września; przeczytany na stronie repozytorium i w rekordzie OSV 1 października 2026. Opis wpływu i pełne zdanie z obejściami cytowane są z biuletynu; wiersz Patches w rekordzie OSV brzmi „Fixed in 1.96.2, 1.95.1, 1.94.3, 1.93.2, 1.92.2, 1.91.5, 1.90.7, 1.89.7, and 1.88.6”, a strona repozytorium podaje „Affected versions <1.94.0”. Liczba jedenaście to wpisy PYSEC-2026-4066 do PYSEC-2026-4076 w bazie biuletynów PyPA, wszystkie dla pakietu
litellm, każdy z datą 1 października 2026, żaden niewycofany. ↩↩↩↩↩ -
Anthropic, Hooks reference, dokumentacja Claude Code, pobrana 2 października 2026. PreToolUse uruchamia się „Before a tool call executes. Can block it” (zanim wywołanie narzędzia zostanie wykonane; może je zablokować); PostToolUse uruchamia się „After a tool call succeeds” (po udanym wywołaniu narzędzia); „Any other exit code doesn’t block on its own for most hook events” (dla większości zdarzeń inny kod wyjścia sam niczego nie blokuje); hook polecenia, który przekroczy limit czasu, „doesn’t block the tool call” (nie blokuje wywołania narzędzia), a „a mistyped path in settings.json leaves the gate silently disabled” (literówka w ścieżce w settings.json po cichu wyłącza zabezpieczenie). ↩↩↩
-
Biuletyn GitHub Security Advisory GHSA-hx8v-g79f-8w5f (CVE-2026-59823, PYSEC-2026-4070), „LiteLLM Proxy has server-side request forgery via the
user_configrequest parameter”, opublikowany 17 września 2026, przeczytany przez OSV 1 października 2026: podatne<= 1.83.8, poprawka1.83.9, przy czym biuletyn datuje to wydanie na 17 kwietnia 2026. ↩ -
Rekordy OSV przeczytane 1 października 2026: PYSEC-2026-4067 (CVE-2026-12773, uwierzytelnianie proxy MCP), PYSEC-2026-4069 (CVE-2026-12798, moduł ładujący specyfikacje OpenAPI dla MCP) oraz PYSEC-2026-4068, 4071, 4072, 4073, 4074, 4075 i 4076. Biuletyny GitHuba stojące za tymi dziewięcioma opublikowano 21 czerwca 2026, tego samego dnia, w którym ujęło je NVD, i każdy powołuje się na VulDB. Daty publikacji i aktualna wersja pochodzą ze strony projektu w PyPI i jej JSON-a, odczytanych tego samego dnia: 1.88.6 do 1.95.1 z 9 sierpnia, 1.96.2 z 11 sierpnia, 1.97.0 z 16 sierpnia i 1.103.2 z 1 października. ↩↩↩
-
Odczyt autora pakietu wheel
litellm1.95.0 z PyPI (zakres podatności od 1.95.0 do poprawki w 1.95.1), 1 października 2026: wlitellm/proxy/auth/auth_utils.pyfunkcja_check_banned_paramskończy działanie, zanim cokolwiek odrzuci, gdygeneral_settings.get("allow_client_side_credentials") is True, a w przeciwnym razie odrzuca żądanie, którego treść zawiera parametr z listy zakazanych, chyba żeconfigurable_clientside_auth_paramsdanego wdrożenia dopuszcza ten parametr. Lista zakazanych parametrów obejmuje w tym wydaniuvertex_ai_credentialsoraz poświadczenia i hosty narzędzi obserwowalności. Przeczytałem jedno podatne wydanie, nie wszystkie dziewięć linii. ↩