Ash AI 1.0.0 naprawia sześć CVE: od RCE w promptach po błędy MCP i narzędzi
Sześć podatności w ash_ai pokazuje, że bezpieczeństwo agenta zależy od całego runtime: renderowania promptu, filtrów rekordów, obsługi błędów, MCP i pętli narzędzi.
- AUTOR
- Karol Rapacz / CEO Breachroad · OSCP · PNPT
- PUBLIKACJA
- 31 sierpnia 2026
- CZAS CZYTANIA
- 22 min czytania
- TEMAT
- Bezpieczeństwo AI
Do NVD trafiło dziś sześć podatności biblioteki ash_ai dla ekosystemu Elixir i Ash. Najpoważniejsza z nich, CVE-2026-77956, otrzymała CVSS 4.0 równy 10,0 i może pozwolić zdalnemu, nieuwierzytelnionemu użytkownikowi wykonać kod Elixir na serwerze. Pozostałe problemy obejmują obejście ochrony MCP przed DNS rebindingiem, zmianę lub usunięcie niewłaściwego rekordu przez narzędzie agenta, ujawnianie sekretów w błędach oraz pętlę generującą powtarzające się wywołania modelu.
Wszystkie sześć luk poprawiono w ash_ai 1.0.0. Zakres wersji zależy od konkretnego CVE: część problemów istnieje od 0.1.0, inne od 0.6.0 lub 0.8.0. Advisory projektu opublikowano 30 sierpnia, natomiast rekordy NVD pojawiły się 31 sierpnia czasu warszawskiego. To właśnie wejście kompletu informacji do publicznych feedów podatności jest dzisiejszą nowością.
Ta seria jest cenna również poza społecznością Elixir. Nie opisuje jednego wadliwego warunku, lecz sześć różnych granic zaufania typowych dla aplikacji agentowych: dane zamieniane w kod, model wybierający rekord, przeglądarka łącząca się z lokalnym MCP, nieskończona orkiestracja oraz błędy krążące między narzędziem, modelem i użytkownikiem.
CVE-2026-77956: prompt funkcyjny stawał się kodem Elixir
AshAi.Actions.Prompt obsługiwał prompt zdefiniowany jako funkcja przyjmująca dane wejściowe i kontekst. Wynik funkcji był następnie przekazywany do EEx.eval_string/2. EEx jest mechanizmem szablonów, ale jego znaczniki zawierają wyrażenia Elixir. Jeśli funkcja składała treść z argumentów akcji dostarczonych przez użytkownika, niezaufany fragment nie pozostawał zwykłym tekstem: był kompilowany i wykonywany na serwerze jeszcze przed zapytaniem do modelu.
Nie oznacza to, że każda instalacja ash_ai automatycznie udostępnia RCE. Musi istnieć osiągalna akcja promptowa, której dynamiczna treść zawiera dane z żądania. Jednak taki sposób definiowania promptów był dokumentowany, a atak nie wymaga dodatkowej tożsamości, jeśli sama akcja jest publiczna. Kod działa z uprawnieniami procesu aplikacji, więc potencjalny wpływ obejmuje sekrety środowiskowe, połączenia do baz, pliki dostępne dla kontenera i możliwość dalszego ruchu z sieci usługi.
Poprawka rozdziela dwa przypadki. Statycznie skonfigurowany szablon nadal może korzystać z EEx, natomiast treść zwrócona przez funkcję nie jest ponownie interpretowana jako kod szablonu. To właściwa granica: funkcja aplikacji może świadomie zbudować tekst, ale dane runtime nie powinny otrzymywać drugiej, ukrytej fazy ewaluacji.
CVE-2026-81315: DNS rebinding przy lokalnym serwerze MCP
Druga luka dotyczy serwera MCP i domyślnego allowed_origins: nil. Kontrola origin dopuszczała żądanie, gdy host z Origin odpowiadał hostowi połączenia, a schemat przekazany przez proxy wskazywał HTTPS. Problem polegał na tym, że obie przesłanki dało się ukształtować po stronie żądania: conn.host wynikał z nagłówka Host, natomiast schemat był czytany z surowego X-Forwarded-Proto bez sprawdzenia, czy żądanie rzeczywiście przeszło przez zaufane proxy.
W scenariuszu DNS rebindingu domena napastnika najpierw wskazuje jego serwer, a później adres lokalny ofiary. Przeglądarka zachowuje origin domeny, lecz łączy się już z lokalnym MCP. Odpowiedni Host oraz możliwy do ustawienia X-Forwarded-Proto pozwalały przejść wadliwą kontrolę. Złośliwa strona mogła wówczas wysyłać żądania do MCP w kontekście aktora użytkownika.
CVE-2026-81315 dotyczy wersji od 0.8.0 do 0.9.x i ma CVSS 4.0 równy 7,4. W 1.0.0 domyślnie zaufane są tylko originy localhost, a każdy inny wymaga jawnej allowlisty. Operator nadal powinien upewnić się, że proces nasłuchuje wyłącznie na potrzebnym interfejsie, proxy nadpisuje zamiast dopisywać nagłówki przekazywane i że nieużywane endpointy MCP nie są wystawione.
CVE-2026-82564: mapa w identyfikatorze zmieniała znaczenie filtra
Narzędzia aktualizujące i usuwające rekord budowały filtr tożsamości bezpośrednio z surowych argumentów modelu. Oczekiwano wartości identyfikatora, lecz mapa była interpretowana przez warstwę zapytań jako wyrażenie predykatu. Zamiast porównania pola do literału powstawał warunek sterowany przez wywołującego. Pominięty klucz mógł z kolei zbudować dopasowanie do NULL.
Skutek jest poważny, bo model lub użytkownik sterujący argumentem narzędzia mógł przekierować operację na rekord, którego nie wskazał. Przy operacji zbiorczej i limicie jeden ofiarą mógł zostać dowolny pasujący rekord; w pewnych konfiguracjach filtr mógł objąć znacznie szerszy zbiór. Autoryzacja w zasobie nadal może ograniczyć wpływ, ale nie wolno zakładać, że naprawi błędną selekcję obiektu.
Poprawka 1.0.0 rzutuje każdą wartość tożsamości do typu pola i odrzuca wejście nieskalarne. CVE-2026-82564 obejmuje wersje od 0.6.0 i ma wynik 7,1. To przykład klasycznego błędu „data versus expression”: struktura, która na granicy API wygląda jak JSON, po wejściu do DSL filtra nabiera semantyki programu.
Dwa kanały ujawniania błędów
CVE-2026-75760 dotyczy procesu wektoryzacji. Gdy dostawca embeddingów zwracał błąd, AshAi.Changes.Vectorize umieszczał inspect(error) w błędzie walidacji changesetu. AshJsonApi i AshGraphql mogły odesłać taki komunikat użytkownikowi. Surowa struktura klienta HTTP może zawierać URL, ciało odpowiedzi dostawcy, stan żądania, a czasem nagłówek Authorization z kluczem API. Nadmiernie duża lub niepoprawna treść kierowana do wektoryzacji może celowo wywołać tę ścieżkę.
CVE-2026-82580 znajduje podobny problem w pętli narzędzi. Wyjątek powstały w callbacku lub hooku był zamieniany przez Exception.message/1 na rezultat narzędzia, dopisywany do rozmowy, emitowany w strumieniu i ponownie wysyłany do modelu. Użytkownik mógł więc zobaczyć szczegóły ograniczeń bazy, fragmenty zapytań, nazwy adapterów, polityki lub dane walidacyjne. Model tworzył dodatkowy kanał propagacji: nawet jeśli frontend nie wyświetlił struktury technicznej bezpośrednio, treść pozostawała w kontekście i mogła wrócić w odpowiedzi językowej.
Pierwsza luka ma CVSS 7,1 i obejmuje wersje od 0.1.0; druga ma 5,3 i obejmuje wersje od 0.6.0. W poprawionej wersji szczegóły są logowane po stronie zaufanej, a klient otrzymuje ogólny komunikat. Logowanie także wymaga kontroli: centralny system logów powinien maskować sekrety, ograniczać dostęp i mieć rozsądną retencję.
CVE-2026-82579: pętla bez postępu zamienia błąd modelu w koszt
Pętla narzędzi klasyfikowała odpowiedź modelu jako tool_calls, a następnie normalizowała i odfiltrowywała wywołania. Wywołanie bez poprawnej nazwy albo z ponownie użytym tool_call_id mogło zniknąć. Jeśli po filtracji lista była pusta, implementacja nie dopisywała nowej wiadomości, ale wykonywała kolejną iterację na identycznej historii.
Model otrzymywał więc dokładnie ten sam kontekst i mógł generować ten sam rezultat. Przy wspieranym ustawieniu max_iterations: :infinity pętla nie miała końca; przy limicie zużywała cały budżet. Wpływ to nie tylko zajęty worker. Każda iteracja może oznaczać płatne zapytanie do dostawcy, utrzymywane połączenie i kumulację opóźnień. Wstrzyknięcie instrukcji do dokumentu lub innego kontekstu może nakłonić model do ponawiania zużytego identyfikatora.
Wersja 1.0.0 traktuje pustą listę po filtracji jako stan terminalny. Niezależnie od aktualizacji organizacja powinna stosować skończony limit iteracji, deadline całego zadania, budżet tokenów i kosztu, idempotencję narzędzi oraz telemetrię wykrywającą brak postępu.
Kogo dotyczy problem i jak ustalić ekspozycję
Najpierw znajdź ash_ai nie tylko w pliku deklaracji, lecz w artefakcie wdrożonym produkcyjnie. Ustal dokładną wersję, punkty wejścia i konfigurację. Następnie przeprowadź krótką analizę osiągalności:
- wyszukaj akcje
AshAi.Actions.Promptużywające funkcji i sprawdź, czy w wyniku znajduje się wejście użytkownika; - zinwentaryzuj serwery MCP, interfejsy nasłuchu,
allowed_originsoraz zaufane proxy; - wypisz narzędzia update/destroy oparte na identity i polityki autoryzacji zasobów;
- sprawdź, które pola są wektoryzowane z treści klienta i jak API prezentuje błędy;
- przejrzyj callbacki narzędzi pod kątem wyjątków zawierających dane wewnętrzne;
- potwierdź limit iteracji, czas całkowity i budżet każdego przebiegu agenta.
Najpilniejsza jest aktualizacja do 1.0.0 lub późniejszej zgodnej wersji. Jeśli wdrożenie musi poczekać, wyłącz osiągalne akcje z dynamicznym EEx, odetnij MCP od niezaufanej sieci, ustaw ścisłą allowlistę originów, wyłącz narzędzia modyfikujące dane i zastąp szczegółowe błędy bezpiecznym komunikatem. To redukcja ekspozycji, a nie równoważnik patcha.
Po aktualizacji wykonaj testy regresji na małych, kontrolowanych danych. Test powinien wykazać, że znaczniki EEx w argumencie pozostają tekstem, wartości złożone nie mogą stać się filtrem identity, nieznany origin jest odrzucany, wyjątek nie pojawia się w odpowiedzi i pętla kończy się, gdy wszystkie wywołania odpadną podczas normalizacji. Nie trzeba odtwarzać destrukcyjnego RCE ani obciążać produkcyjnego modelu.
Detekcja i reakcja
Przejrzyj logi procesu Elixir pod kątem nietypowych wywołań systemowych, dostępu do plików i procesów potomnych skorelowanych z akcjami promptowymi. Sprawdź nagłe błędy dostawcy embeddingów, odpowiedzi API zawierające nazwy nagłówków lub fragmenty struktur HTTP, operacje update/destroy bez spodziewanego identyfikatora oraz wielokrotne wywołania modelu z tym samym hashem historii i tool_call_id.
Dla MCP przydatne są żądania z publicznym Origin kierowane do adresu lokalnego, niespodziewany X-Forwarded-Proto poza proxy i rozbieżność między interfejsem sieciowym a przeznaczeniem usługi. Jeśli istnieje podejrzenie wykorzystania CVE-2026-77956, aktualizacja nie kończy dochodzenia: trzeba obrócić sekrety dostępne procesowi, sprawdzić integralność obrazów i plików, historię procesów oraz połączenia wychodzące.
Fakty źródłowe i wnioski Breachroad
Zakresy wersji, oceny CVSS, mechanizmy i wydanie naprawcze pochodzą z rekordów CVE, advisory projektu oraz commitów ash_ai. Kolejność przeglądu, model telemetrii i rekomendowane bariery kosztowe są wnioskami obronnymi Breachroad. Źródła nie stwierdzają potwierdzonego wykorzystania tych sześciu luk w środowiskach produkcyjnych. Obecność podatnej wersji jest dowodem ekspozycji, nie dowodem włamania.
Źródła pierwotne
- GHSA dla krytycznego RCE — CVE-2026-77956
- GHSA dla DNS rebindingu MCP — CVE-2026-81315
- GHSA dla ujawnienia błędu wektoryzacji — CVE-2026-75760
- GHSA dla filtra identity — CVE-2026-82564
- GHSA dla pętli narzędzi — CVE-2026-82579
- GHSA dla ujawniania wyjątków narzędzi — CVE-2026-82580
- CNA Erlang Ecosystem Foundation: CVE-2026-77956
- NVD: CVE-2026-77956
Agent nie jest bezpieczny tylko dlatego, że model nie wykonuje kodu samodzielnie. Na warsztatach z bezpiecznych wdrożeń AI uczymy zespoły projektować granice promptów, narzędzi, danych i kosztu jako jeden system. Gdy potrzebna jest niezależna weryfikacja realnej ścieżki nadużycia, uzupełnieniem może być kontrolowany AI red teaming.


