Bezpieczeństwo CI/CD
Zatrzymywanie eksfiltracji z GitHub Actions za pomocą polityki ruchu wychodzącego
Zadanie CI ma dostęp do sekretów i uruchamia kod pobrany przed chwilą: akcje, pakiety i ich skrypty instalacyjne. Jeśli którykolwiek z tych elementów jest złośliwy, najłatwiej ukraść sekrety, wysyłając je na serwer. Polityka ruchu wychodzącego określa, z którymi serwerami zadanie może się łączyć, i blokuje resztę.
Zaktualizowano
Jak sekrety wydostają się z zadania CI
Zadanie ma dostęp do tokenu repozytorium, przekazanych mu sekretów i wszelkich poświadczeń chmurowych, z których korzysta. Kod uruchomiony w zadaniu może je odczytać. Następnie może je wyprowadzić na kilka sposobów:
- Przez sieć. Żądanie do serwera kontrolowanego przez napastnika. To kanał, który zamyka polityka ruchu wychodzącego.
- Przez logi. Wypisanie sekretów, często zakodowanych, do logu zadania. W marcu 2025 r. CISA poinformowała, że przejęta akcja tj-actions/changed-files ujawniła sekrety właśnie w ten sposób.
- Przez dane wyjściowe. Artefakty, cache lub commity wypychane z użyciem tokenu zadania.
Kod nie musi być złośliwym pakietem. Agenta AI w workflow można przejąć przez prompt injection ukryte w zgłoszeniu lub pull requeście, a następnie wykorzysta on te same kanały.
Co robi polityka ruchu wychodzącego
Większość zadań musi się łączyć z krótką listą celów: rejestrami pakietów, rejestrami kontenerów, hostami źródeł i kilkoma usługami. Polityka ruchu wychodzącego dopuszcza tę listę i blokuje wszystko inne. Przy polityce domyślnej odmowy żądanie do nieznanego hosta kończy się niepowodzeniem, a sekrety pozostają w zadaniu.
Nie zamyka to wszystkich dróg:
- Nie zapobiega wypisywaniu sekretów do logów. Należy utrzymywać logi jako prywatne i przypinać akcje do commit SHA.
- Dozwolony cel nadal może posłużyć do wyprowadzenia danych, dlatego lista dozwolonych celów powinna być wąska.
- Nie wskazuje, które pakiety były złośliwe. To zadanie weryfikacji pakietów i SBOM.
Trzy sposoby egzekwowania
- Agent na runnerze. StepSecurity Harden-Runner jest dodawany jako pierwszy krok zadania. Przypisuje każde połączenie do kroku, który je nawiązał, buduje punkt odniesienia w trybie audytu i blokuje ruch wychodzący do wszystkiego, czego nie ma na liście dozwolonych celów.
- Runner z wbudowaną polityką. CRACI egzekwuje politykę jako sam runner. Inni dostawcy runnerów także oferują kontrole sieciowe, na przykład filtrowanie ruchu wychodzącego na linuksowych runnerach Depot oraz polityki ruchu wychodzącego w trybie blokowania lub doradczym w Namespace.
- Własna sieć. Runnery self-hosted za firewallem lub proxy, które sami Państwo konfigurują i utrzymują.
Wdrożenie bez psucia buildów
- Obserwacja. Rejestrowanie każdego połączenia zadania przez kilka uruchomień.
- Dopuszczenie. Zbudowanie listy dozwolonych celów na podstawie tego, czego zadanie faktycznie potrzebuje.
- Blokowanie. Przejście na domyślną odmowę i obserwowanie naruszeń.
- Przegląd. Traktowanie każdego nowego naruszenia albo jako brakującego źródła, albo jako incydentu.
Jak robi to CRACI
W CRACI polityka ruchu wychodzącego jest częścią runnera. Jest walidowana przed uruchomieniem zadania, nieznane pola są odrzucane, a w razie awarii ruch jest blokowany. Wbudowane presety obejmują popularne źródła pakietów, a resztę dodają niestandardowe źródła i połączenia. Ślad zadania wymienia każde połączenie, a każde zablokowane jako naruszenie wraz z przyczyną. Ponieważ proxy rozpoznaje pakiety, ten sam zapis staje się SBOM zadania. API zwraca SBOM-y, ślady sieciowe i dane o pochodzeniu.
CRACI nie ma jeszcze dedykowanego trybu audytu; jest on w planach rozwoju. Bez polityki sieciowej ruch zadania jest dozwolony i zapisywany w śladzie, dzięki czemu widzą Państwo, czego polityka będzie potrzebować, zanim zaczną ją Państwo egzekwować. CRACI uruchamia zadania GitHub Actions na Linuksie. Zob. porównanie narzędzi bezpieczeństwa CI/CD oraz CRACI a StepSecurity.
Polityki ruchu wychodzącego w CI: najczęściej zadawane pytania
Czym jest polityka ruchu wychodzącego w CI?
To zestaw reguł dla wychodzących połączeń sieciowych, które może nawiązywać zadanie CI. Zadanie ma dostęp do potrzebnych rejestrów pakietów i usług, a każdy inny cel jest blokowany.
Czy polityka ruchu wychodzącego zatrzymałaby atak na tj-actions?
Sama nie. W tym przypadku CISA poinformowała, że sekrety ujawniono przez logi workflow, a nie wysłano na zewnętrzny serwer. Polityka ruchu wychodzącego zamyka kanał sieciowy; kanał logów zabezpiecza się przez przypinanie akcji do commit SHA i utrzymywanie logów jako prywatnych.
Czy blokowanie ruchu wychodzącego psuje buildy?
Może, jeśli polityka pominie źródło potrzebne buildowi. Należy zacząć od zarejestrowania, z czym łączy się zadanie, na tej podstawie zbudować listę dozwolonych celów, a dopiero potem blokować. W CRACI wbudowane presety obejmują popularne źródła pakietów, a zablokowane połączenie jest widoczne w śladzie zadania wraz z przyczyną.
Czy można stosować politykę ruchu wychodzącego na runnerach hostowanych przez GitHub?
Tak, po dodaniu do zadania agenta, takiego jak StepSecurity Harden-Runner. Można też przenieść zadanie na runner, który sam egzekwuje politykę, taki jak CRACI.
Proszę objąć jedno zadanie polityką ruchu wychodzącego
Proszę uruchomić jeden workflow na CRACI i zobaczyć każde nawiązane połączenie, te, które zablokowałaby polityka domyślnej odmowy, oraz SBOM tego, co pobrał.
Umów demo