Logo StartupKit
PL

Jak działa izolacja sieciowa

Model bezpieczeństwa triażu AI z dostępem do kodu. Wyjaśnia, dlaczego granica sieciowa znajduje się poza agentem, jak odizolować runner GitLab i jak ograniczyć ryzyko wycieku kodu przez złośliwe zgłoszenie.

Przed czym chroni izolacja

Agent triażu AI z dostępem do kodu dostaje jednocześnie kod źródłowy i treść zgłoszenia kontrolowaną przez napastnika. Taka kombinacja naraża agenta na prompt injection. Złośliwy badacz może opisać problem tak, żeby przejąć sterowanie agentem, odczytać sekrety i wysłać je przez curl do zewnętrznego hosta.

Ograniczenia sieciowe trzeba egzekwować poza agentem, w jego środowisku. Mają blokować połączenia z odbiorcami spoza dozwolonej listy, także gdy model wykona złośliwą instrukcję. Poniżej opisano taką konfigurację, z wyjątkami dla modelu i MCP Kit.

Danger

Każdą treść zgłoszenia traktuj jako wrogą. Prompt triażu otacza pola separatorami i zabrania modelowi wykonywać znalezione w nich instrukcje. Takie oddzielenie danych od instrukcji jest dodatkową warstwą ochrony, nie właściwą granicą. Granicę stanowią opisane niżej reguły blokowania ruchu z jawnie określonymi wyjątkami.

Główna zasada: zamknięcie na poziomie środowiska

Najważniejsza decyzja projektowa brzmi: własna allowlista sieciowa agenta nigdy nie jest granicą bezpieczeństwa. Wytyczne Anthropic dotyczące zamykania systemów agentowych mówią wprost, żeby najpierw projektować ograniczenia na poziomie środowiska, a reguły narzucone samemu agentowi traktować wyłącznie jako kolejną warstwę ochrony.

Własna allowlista agenta nie nadaje się na granicę z konkretnych powodów:

  • Allowlisty bywają omijane. Claude Code otrzymywał poprawki prawdziwych podatności omijających allowlistę, w tym błędu jej odczytu i różnicy w parserze SOCKS5, gdzie bajt null pozwalał obejść każdą allowlistę z wildcardem. Przypinaj nowe wersje, ale nie opieraj całej ochrony na allowliście.
  • Dozwolone domeny mają dodatkowe endpointy, które mogą posłużyć do wycieku. Domena dostawcy LLM może oprócz endpointu modelu udostępniać API plików, uploadu albo storage. Reguła „zezwól na endpoint modelu” może dopuścić taki kanał wyprowadzania danych.

Ograniczenia odbiorców danych muszą więc działać poza agentem, w konfiguracji sieci i runnera. Dozwolone endpointy nadal otrzymują dane potrzebne do analizy i zapisania wyniku.

Granica: blokada całego ruchu wychodzącego i proxy z dwoma celami

Izolację tworzą cztery zabezpieczenia na poziomie środowiska. Przykładowe repozytorium pokazuje wszystkie w .gitlab-ci.yml i katalogu infra/.

1. Samodzielnie zarządzany runner GitLab

Musisz użyć samodzielnie zarządzanego runnera. Współdzielonych runnerów GitLab.com SaaS nie da się odizolować od sieci hosta po twojej stronie, więc nie wyegzekwujesz na nich granicy ruchu wychodzącego. README przykładowego repozytorium wskazuje to jako warunek izolacji.

2. Nieuprzywilejowany executor Docker

Ustawienie Wartość Po co
privileged false Tryb uprzywilejowany daje w praktyce uprawnienia root hosta. Nie wolno go używać na ścieżce niezaufanych zgłoszeń.
Uruchom jako użytkownik inny niż root Usuń SETUID/SETGID oraz wszystkie zbędne capabilities.
Socket Docker niezamontowany Zamontowany socket pozwala przejąć hosta.
Wolumeny hosta brak Nie montuj katalogów hosta w zadaniu.
FF_NETWORK_PER_BUILD 1 GitLab tworzy osobną sieć bridge dla każdego zadania i usuwa ją po zakończeniu, dzięki czemu sieć jest odizolowana i powtarzalna.
# config.toml on your self-managed runner
[[runners]]
  executor = "docker"
  environment = ["FF_NETWORK_PER_BUILD=1"]
  [runners.docker]
    privileged = false

3. Blokada ruchu wychodzącego na poziomie hosta

Warning

GitLab Runner nie ma natywnej allowlisty ruchu wychodzącego. Nie istnieje wbudowane ustawienie „pozwól zadaniom łączyć się tylko z tymi hostami”. Taka funkcja została zaproponowana, ale jej nie wydano. Granicę trzeba wyegzekwować na poziomie hosta albo namespace.

Ustaw domyślną politykę DROP dla ruchu wychodzącego z sieci zadania przy użyciu iptables/nftables albo uruchom zadanie w namespace sieci bez trasy do intranetu. Domyślnie blokuj wszystko, a następnie otwórz dokładnie dwa opisane niżej cele. Nie dopuszczaj niczego więcej, również własnej sieci wewnętrznej.

4. Proxy kończące TLS i sprawdzające token

Jedyna dozwolona droga na zewnątrz prowadzi przez proxy, które dopuszcza dokładnie dwa cele:

  1. Twój endpoint inferencji LLM, np. https://api.deepseek.com/anthropic.
  2. Ograniczony host MCP Kit, służący do odczytu zgłoszenia i odesłania triażu.

Proxy dopuszcza tylko te dwa hosty. Dodatkowo:

  • ogranicza ruch do ścieżek inferencji i MCP, dzięki czemu API plików lub storage dostawcy LLM pozostają zablokowane mimo dozwolonego hosta;
  • sprawdza token sesji osobny dla każdego przebiegu, więc napastnik, który przemyci własny klucz API do agenta, nie może go użyć. Proxy honoruje wyłącznie token utworzony dla danego przebiegu.

Odpowiada to wzorcowi proxy MITM wewnątrz maszyny wirtualnej, którego Anthropic używa do izolowania własnych agentów. Filtr ruchu wychodzącego w stylu harden-runner jest rozsądnym wzorcem dla implementacji referencyjnej.

Maskowanie sekretów w logach

Klucz modelu przechowuj jako maskowaną i chronioną zmienną CI. Token MCP Kit przekazuje osobno przy uruchomieniu pipeline’u. Unikaj wypisywania obu wartości w logach i sprawdź, czy logi testowego przebiegu ich nie ujawniają.

Important

Maskowanie jedynie zastępuje wartość w logach ciągiem [MASKED]. Przejęte zadanie nadal może odczytać wartość zmiennej podczas działania. Dokumentacja GitLab wprost mówi, że maskowanie nie jest niezawodnym zabezpieczeniem. Ograniczenie ruchu wychodzącego blokuje niedozwolonych odbiorców; maskowanie jedynie ogranicza ujawnianie wartości w logach.

Dlatego ograniczony token ma znaczenie: nawet jeśli przejęte zadanie go odczyta, token obejmuje jedno zgłoszenie przez jedną godzinę i pozwala tylko raz zapisać wynik. Reguły sieciowe blokują pozostałe cele, ale pozostawiają dostęp do endpointu modelu i MCP Kit.

Sprawdź blokadę na zgłoszeniu testowym

Przykładowe repozytorium zawiera zgłoszenie testowe (examples/sample-report) z kanarkiem prompt injection, czyli tekstem próbującym wywołać zewnętrzny host przez curl. Uruchom dla niego pipeline i potwierdź, że granica ruchu wychodzącego blokuje wywołanie. Jeśli żądanie kanarka przejdzie, środowisko nie jest odizolowane. Napraw firewall hosta przed połączeniem z Kit.

Kilka słów o wyborze modelu

Kontrolujesz model, więc odpowiadasz także za związane z nim ryzyko. Przesyłanie kodu źródłowego i niezaufanych zgłoszeń do hostowanego endpointu, domyślnie API DeepSeek, to twoja decyzja dotycząca miejsca przetwarzania danych i zaufania. Jeśli sytuacja tego wymaga, skieruj agenta do samodzielnie hostowanego endpointu, takiego jak lokalny vLLM albo proxy Ollama–Anthropic, żeby inferencja nigdy nie opuszczała twojej infrastruktury. Zwraca na to uwagę SECURITY.md w przykładowym repozytorium.

Lista kontrolna

  • Samodzielnie zarządzany runner GitLab, nie współdzielone runnery SaaS
  • Executor Docker z privileged = false, użytkownikiem innym niż root, bez socketu Docker i wolumenów hosta
  • FF_NETWORK_PER_BUILD=1, żeby każde zadanie miało osobną sieć
  • Domyślna polityka DROP ruchu wychodzącego na poziomie hosta przez iptables/nftables albo namespace sieci
  • Proxy ruchu wychodzącego dopuszczające dokładnie dwa hosty i ścieżki: endpoint LLM oraz host MCP Kit
  • Proxy sprawdza token przebiegu i blokuje interfejsy przechowywania plików dostawcy LLM
  • Ograniczony token traktowany jako ważny dla jednego zgłoszenia, przez jedną godzinę i jeden zapis; maskowanie ogranicza ujawnianie sekretów w logach
  • Uruchom próbkę z kanarkiem prompt injection i potwierdź blokadę próby wycieku
  • Przypnij aktualną wersję Claude Code i środowiska sandbox; to dodatkowa warstwa, nie właściwa granica

Co dalej

Wpisz, aby wyszukać...