Pierwsze oświadczenie (holding statement) warto wysłać w ciągu kilku godzin, potwierdzoną odpowiedź, gdy tylko da się ją udowodnić, a dalsze informacje za każdym razem, gdy coś się zmieni. Proszę mówić, co wiadomo, co jest jeszcze sprawdzane i kiedy nastąpi aktualizacja. Każde „nie dotyczy” powinno opierać się na tym, co Państwa buildy faktycznie zainstalowały w oknie ataku, a nie na dzisiejszym lockfile.

Ten tekst dotyczy tego, co powiedzieć, kiedy i na jakiej podstawie. Samo dochodzenie, czyli ustalenie, czy podatny komponent jest w Państwa produktach i od kiedy, opisuje tekst czy to nas dotyczy?.

Dlaczego klienci pytają Państwa, a nie rejestr pakietów

Tydzień po szeroko opisywanym ataku, jak opowiedział nam właściciel małej firmy programistycznej, klienci wysyłali mu SMS-y: czy wasze oprogramowanie jest bezpieczne? Czy moje jest bezpieczne? Jego klienci przetwarzają dane wrażliwe, w jego zespole nie ma specjalisty ds. bezpieczeństwa, a odpowiedź była potrzebna tego samego dnia.

Klienci nie pytają, czy pakiet został przejęty. Rejestr i badacze już to ogłosili. Pytają, czy to, co im Państwo dostarczyli, go zawiera, bo Państwa produkt to ich ekspozycja. Ich właśni klienci, audytorzy lub regulatorzy zadają im to samo pytanie. W regulowanych łańcuchach dostaw, takich jak półprzewodniki, urządzenia przemysłowe i ochrona zdrowia, to pytanie wynika z umowy, a nie z ciekawości.

Zapytają też ponownie, jeśli odpowiedzi nie da się sprawdzić. „Nie dotyczy nas” bez niczego za tym to obietnica; „sprawdziliśmy każdy build wydania od 24 do 31 marca i żaden nie zainstalował dotkniętych wersji” to stwierdzenie, na którym mogą polegać.

Cztery niedawne ataki i pytanie, które każdy z nich postawił

Właściwa odpowiedź zależy od tego, jak przebiegał atak, więc sam szablon nie wystarczy. W każdym z tych przypadków jeden fakt decyduje o tym, co „dotyczy” oznacza dla dostawcy.

Backdoor w xz Utils (CVE-2024-3094), ujawniony 29 marca 2024. Andres Freund znalazł backdoor w wersjach xz 5.6.0 i 5.6.1. Archiwa tar wydań zawierały kod, którego nie było w repozytorium Git, i to on wstrzykiwał backdoor podczas buildu. NVD i Red Hat oceniają go na 10.0 w CVSS 3.1. Trafił głównie do dystrybucji rolling i testowych: Debian testing, unstable i experimental, Fedora Rawhide i 41, openSUSE Tumbleweed i Kali, natomiast wydania stabilne nie były dotknięte. Pytanie, które postawił: czy jakikolwiek dostarczony przez nas obraz lub urządzenie zawiera xz 5.6.0 lub 5.6.1 i jakiego obrazu bazowego użył każdy build?

Robak npm Shai-Hulud, falami od września 2025. Zainfekowane pakiety uruchamiają podczas instalacji skrypt, który kradnie poświadczenia npm, GitHub i chmury i używa ich do publikowania zainfekowanych wersji kolejnych pakietów. Pytanie, które postawił: czy jakiekolwiek zadanie CI zainstalowało zainfekowaną wersję i czy nasze tokeny publikacyjne zostały ujawnione, co uczyniłoby z nas roznosiciela? Nasz wpis o Shai-Hulud wymienia każdą falę i opisuje, jak to sprawdzić.

LiteLLM w PyPI, 24 marca 2026. Wersje 1.82.7 i 1.82.8 zostały wgrane bezpośrednio do PyPI z kodem kradnącym poświadczenia, którego nigdy nie było w repozytorium projektu na GitHubie. W wersji 1.82.8 plik .pth uruchamiał ładunek przy każdym starcie dowolnego interpretera Pythona, a nie tylko przy imporcie LiteLLM; zbierał zmienne środowiskowe, klucze SSH, poświadczenia chmurowe i sekrety Kubernetes. HiddenLayer wiąże atak z grupą TeamPCP, która w tym samym miesiącu zaatakowała też narzędzia Trivy i Checkmarx. Sam biuletyn LiteLLM podaje dwa wyjaśnienia początkowego dostępu: wskazuje zależność Trivy w swoim workflow skanowania bezpieczeństwa w CI, a zarazem pisze, że konto PyPI jednego z opiekunów mogło zostać przejęte. Nawet okno ekspozycji różni się w tym samym biuletynie: w jednym miejscu około 40 minut, w innym od 10:39 do 16:00 UTC. Pytanie, które postawił: czy build lub dostarczony kontener zawierał te wersje i jakie sekrety były obecne w tym środowisku?

axios w npm, 31 marca 2026. Atakujący przejął konto npm jednego z opiekunów i opublikował axios 1.14.1 i 0.30.4, które dodawały zależność [email protected], której skrypt instalacyjny instalował trojana zdalnego dostępu dla macOS, Windows i Linux. Datadog podaje okno od 00:21 do 03:25 UTC; według Snyk wersje usunięto o 03:29 UTC. Pytanie, które postawił: czy jakikolwiek build rozwiązał te wersje w tym oknie? Lockfile zatwierdzony przed oknem daje odpowiedź „nie” dla buildów, które go użyły, i nie mówi nic o buildach, które uruchomiły npm install bez niego.

AtakEkosystemDotknięte wersjeOknoCo „dotyczy” oznacza dla dostawcy
xz UtilsDystrybucje Linux5.6.0, 5.6.1Tygodnie, do ujawnienia 29 marca 2024Dostarczyli go Państwo w obrazie lub urządzeniu zbudowanym na dotkniętej dystrybucji
Shai-HuludnpmSetki pakietów, w każdej faliOd godzin do dni w każdej faliBudowali Państwo z nim, a Państwa tokeny mogły go roznieść; mogli go też Państwo dostarczyć
LiteLLMPyPI1.82.7, 1.82.824 marca 2026, od 10:39 UTC (źródła różnią się co do końca)Budowali Państwo z nim lub go dostarczyli, a sekrety z tego środowiska mogły zostać skradzione
axiosnpm1.14.1, 0.30.431 marca 2026, około 00:21 do 03:25 UTCBudowali Państwo z nim w oknie ataku; trojan uruchomił się na maszynie buildu

Te same pytania pojawiają się przy krytycznej podatności, która nie jest atakiem na łańcuch dostaw. Gdy w październiku 2026 roku wykorzystywano PHP2Shell, klienci każdego produktu zawierającego PHP pytali, które z ich wersji mają dotknięte PHP. Poniższe kroki obowiązują bez zmian.

Odpowiedź ma trzy etapy

EtapKiedyCo Państwo wysyłają
Pierwsze oświadczenieW ciągu kilku godzin od wiadomościCo wiadomo, co jest sprawdzane, kiedy będzie aktualizacja
Potwierdzona odpowiedźGdy tylko da się ją udowodnić, zwykle pierwszego dnia„Nie dotyczy” dla wskazanych wersji lub „dotyczy” z instrukcją
Dalsze informacjeGdy pojawi się poprawka, gdy dowiedzą się Państwo czegoś nowego, przy zamknięciu sprawyTen sam komunikat, zaktualizowany

Pierwsza godzina: pierwsze oświadczenie

Pierwsze oświadczenie to pierwszy publiczny komunikat wydany, zanim znane są fakty. Proszę powiedzieć coś prawdziwego, i to szybko. Milczenie wypełniają domysły, a klient, który nic od Państwa nie słyszy, zakłada, że Państwo niczego nie zauważyli.

  • Kto i gdzie. Jeden imiennie wskazany nadawca, w kanale, którego użył klient, plus Państwa strona bezpieczeństwa. Jeden wspólny tekst jest lepszy niż doraźne odpowiedzi: pozostaje spójny, a dział prawny sprawdza go raz.
  • Co zawiera. Że wiedzą Państwo o ataku, że sprawdzają Państwo swoje produkty i systemy buildów, co wiadomo do tej pory, kiedy nastąpi kolejna aktualizacja i z kim się kontaktować.
  • Czego nie może zawierać. „Nie dotyczy nas” przed sprawdzeniem, spekulacji o atakującym ani obwiniania kogokolwiek.

Szablon 1: pierwsze oświadczenie

Temat: [nazwa ataku]: nasze pierwsze oświadczenie

Szanowni Państwo, wiemy o zgłoszonym przejęciu [pakiet lub projekt] ([dotknięte wersje], opublikowane [data]). Nasz zespół bezpieczeństwa sprawdza każde wydanie [produkt] oraz nasze systemy buildów pod kątem dotkniętych wersji. Do tej pory [nie znaleźliśmy dotkniętych wersji w sprawdzonych produktach / nie zakończyliśmy jeszcze sprawdzania]. Kolejną informację prześlemy do [data i godzina, strefa czasowa]. W razie pytań prosimy o kontakt: [imię i nazwisko, adres kontaktowy ds. bezpieczeństwa]. Nie będziemy spekulować o skutkach przed zakończeniem sprawdzania.

W SMS-ie lub na czacie wystarczą dwa zdania:

Wiemy o przejęciu [nazwa ataku] i właśnie sprawdzamy każde wydanie [produkt] oraz nasze buildy. Potwierdzoną odpowiedź prześlemy Państwu do [godzina].

Wszystkie trzy szablony warto dać do zatwierdzenia prawnikom, zanim będą potrzebne.

Pierwszy dzień: potwierdzenie z dowodami

Możliwe są dwa wyniki i każdy wymaga własnych dowodów. Dla odpowiedzi „nie dotyczy” należy zebrać:

  • dotknięty pakiet i wersje, z biuletynu lub opracowania badaczy
  • swoje produkty i wersje, których klienci faktycznie używają
  • dla każdej z tych wersji build, który ją wytworzył, i zapis tego, co ten build zainstalował, a nie bieżący lockfile
  • każdy build uruchomiony w oknie ataku, łącznie z zadaniami CI, które nigdy nie wytworzyły wydania
  • w przypadku robaków kradnących tokeny: czy w zadaniach, które mogły uruchomić złośliwy kod, były obecne sekrety CI

Tekst czy to nas dotyczy? wyjaśnia, jak ustalić każdy z tych punktów.

Każde Państwa stwierdzenie musi mieć pokrycie w czymś, co można pokazać:

StwierdzenieCo trzeba móc pokazaćCo nie wystarcza
„Produkt X w wersji Y nie zawiera pakietu Z”SBOM zapisany podczas buildu wydania wersji YSkan bieżącego repozytorium
„Żaden z naszych buildów nie zainstalował przejętych wersji”Zapisy instalacji dla każdego buildu w oknieLockfile, który niektóre zadania pomijają
„Nasz pipeline wydań nie został przejęty”Zapisy ruchu sieciowego i użycia sekretów w oknieBrak alertów
„Klienci z wersją Y są bezpieczni po aktualizacji”Zapis buildu z poprawką i poświadczenia, które Państwo wymieniliWpis w changelogu

Szablon 2: nie dotyczy

Temat: [nazwa ataku]: [produkt] nie jest dotknięty

Szanowni Państwo, zakończyliśmy sprawdzanie w związku z przejęciem [pakiet] ([dotknięte wersje]). Następujące wersje [produkt] nie są dotknięte: [lista sprawdzonych produktów i wersji]. Sprawdziliśmy każdy build wydania i każdy build CI uruchomiony między [data początkowa] a [data końcowa]. To oświadczenie opiera się na zapisie komponentów zainstalowanych przez każdy build wydania, a nie na skanie naszego bieżącego kodu źródłowego. Żaden z tych buildów nie zainstalował dotkniętych wersji. Na życzenie możemy przesłać jako dowód SBOM dla używanych przez Państwa wersji lub oświadczenie VEX. Jeśli dowiemy się czegoś, co zmienia tę ocenę, poinformujemy Państwa. Kontakt: [imię i nazwisko, adres kontaktowy ds. bezpieczeństwa].

Proszę pisać „nie dotyczy” dla wskazanych wersji. Nigdy „w 100% bezpieczne”. Jeśli klient poprosi potem o pełny SBOM, pomocny będzie tekst odpowiadanie na prośby klientów o SBOM.

Szablon 3: dotyczy, z instrukcją ograniczenia ryzyka

Temat: [nazwa ataku]: wymagane działanie dla [produkt] w wersjach [od x do y]

Szanowni Państwo, nasze sprawdzanie w związku z przejęciem [pakiet] wykazało, że wersje [produkt] [od x do y] są dotknięte. Pierwszy dotknięty build powstał [data]; wersja [z], wydana [data], nie zawiera już [wersja pakietu].

Co to oznacza: [ryzyko opisane prostym językiem, na przykład „komponent zainstalowany w tych wersjach może wysyłać poświadczenia z systemu, w którym działa, na zewnętrzny serwer”].

Co zrobić teraz: zaktualizować [produkt] do wersji [z]. Jeśli natychmiastowa aktualizacja nie jest możliwa, [środek zaradczy, na przykład zablokowanie połączeń wychodzących do wymienionych hostów]. Jeśli używali Państwo [produkt] w wersjach [od x do y] w środowisku [środowisko], prosimy wymienić [poświadczenia lub klucze], które były w nim dostępne.

Co już zrobiliśmy: usunęliśmy dotknięte wersje z naszych buildów, przebudowaliśmy [produkt] z czystych zależności, wymieniliśmy poświadczenia używane przez nasze systemy buildów oraz [inne działania]. [Tam, gdzie było to wymagane, powiadomiliśmy właściwe organy.]

Kolejną informację prześlemy do [data] lub wcześniej, jeśli coś się zmieni. Kontakt: [imię i nazwisko, adres kontaktowy ds. bezpieczeństwa].

Komunikat „dotyczy” może być też obowiązkiem prawnym; zob. sekcję o raportowaniu poniżej.

Miejsce VEX i CSAF. Oświadczenie „not affected” lub „fixed” można opublikować jako VEX, aby skanery klientów przestały oznaczać pakiet. Więksi klienci mogą oczekiwać także biuletynu w formacie czytelnym maszynowo; CSAF to format, o który pyta większość z nich.

Dalsze informacje: porządne zamknięcie sprawy

Kolejną informację należy wysłać, gdy pojawi się poprawka, gdy dochodzenie przyniesie coś nowego, a końcową notę przy zamknięciu sprawy. Proszę prowadzić jeden biuletyn na incydent i go aktualizować, zamiast za każdym razem wysyłać nowy (aktualizować, nie zastępować). Warto zapisywać, co komu i kiedy Państwo powiedzieli: zapyta o to następny audyt lub kwestionariusz bezpieczeństwa klienta.

Co mówić, gdy jeszcze nic nie wiadomo

„Jeszcze nie wiemy” buduje więcej zaufania niż „nie dotyczy”, które trzeba potem odwołać. Sformułowania uczciwe, a przy tym nikogo niealarmujące:

  • „Nie znaleźliśmy [pakiet] w [dotychczas sprawdzone produkty]. Nadal sprawdzamy [pozostałe produkty lub systemy buildów] i przekażemy informację do [godzina].”
  • „Używane przez Państwa wersje zostały zbudowane przed oknem ataku. Potwierdzamy, że żaden późniejszy build ich nie zastąpił.”
  • „Sprawdzamy, czy którykolwiek z naszych systemów buildów uruchomił dotknięte wersje. Zainstalowany u Państwa produkt to osobna kwestia i odpowiemy na obie.”

Sformułowania, których należy unikać:

  • „Absolutnie żadnego wpływu”
  • „W pełni bezpieczne”
  • „Odporne na wszelkie ataki na łańcuch dostaw”
  • „Nasz skaner niczego nie znalazł”

Kiedy atak staje się obowiązkiem raportowym

Jeśli sprzedają Państwo w UE produkty z elementami cyfrowymi, wymogi raportowania Cyber Resilience Act obowiązują od 11 września 2026 roku, czyli od dnia, w którym ENISA uruchomiła Single Reporting Platform. Aktywnie wykorzystywana podatność w Państwa produkcie lub poważny incydent mający wpływ na jego bezpieczeństwo uruchamia obowiązek wczesnego ostrzeżenia w ciągu 24 godzin od uzyskania o nim wiedzy, zgłoszenia w ciągu 72 godzin i raportu końcowego, składanych przez platformę do koordynującego CSIRT i ENISA. Przewodnik po CRA omawia kolejne kroki.

To, czy dostarczona przez Państwa przejęta zależność lub przejęcie własnego pipeline'u buildów spełnia te definicje, muszą ocenić Państwo wraz z prawnikami, nie ten tekst. Rozporządzenie definiuje pojęcia:

  • „Aktywnie wykorzystywana podatność” to „podatność, w przypadku której istnieją wiarygodne dowody, że złośliwy podmiot wykorzystał ją w systemie bez zgody właściciela systemu” (art. 3 pkt 42).
  • Incydent jest poważny, jeżeli „negatywnie wpływa lub może negatywnie wpłynąć na zdolność produktu z elementami cyfrowymi do ochrony dostępności, autentyczności, integralności lub poufności danych lub funkcji o charakterze szczególnie chronionym lub ważnym” albo jeżeli „doprowadził lub może doprowadzić do wprowadzenia lub uruchomienia złośliwego kodu” w produkcie lub w systemach użytkownika (art. 14 ust. 5).

Artykuł 14(8) dodaje obowiązek wobec użytkowników: poinformować użytkowników, których to dotyczy, a w stosownych przypadkach wszystkich użytkowników, o podatności lub incydencie oraz o wszelkich środkach ograniczających ryzyko, które mogą zastosować, „w stosownych przypadkach w ustrukturyzowanym, nadającym się do odczytu maszynowego formacie, który można łatwo przetwarzać automatycznie”. Szablon 3 może być częścią wypełnienia tego obowiązku.

Obowiązują też inne reżimy. W ramach NIS2 podmioty kluczowe i ważne zgłaszają poważne incydenty swojemu CSIRT lub właściwemu organowi, a wiele umów z klientami zawiera własne klauzule o powiadamianiu, z własnymi terminami.

Przygotowanie przed kolejnym atakiem

  • Zapis tego, co zainstalował każdy build wydania, przechowywany przez okres wsparcia produktu (SBOM-y z czasu buildu).
  • Lista, którzy klienci używają których wersji.
  • Trzy powyższe szablony, zatwierdzone przez dział prawny.
  • Imiennie wskazany nadawca i kanał dla każdego rodzaju klientów.
  • Strona bezpieczeństwa i plik security.txt, gdzie trafiają aktualizacje (skoordynowane ujawnianie podatności).
  • Kontrola ruchu wychodzącego w CI, aby przejęty pakiet nie mógł wysłać sekretów do hosta, którego build nie potrzebuje (polityka egress w GitHub Actions).

Gdy incydenty napływają setkami, a nie pojedynczo, pomocny będzie tekst jak skalować PSIRT.

Miejsce CRACI

Powyższa tabela dowodów wciąż wymaga jednego: zapisu tego, co zainstalował każdy build wydania. Właśnie to przechowuje CRACI. CRACI uruchamia Państwa buildy GitHub Actions na własnych runnerach i rejestruje każdy pakiet, który każde zadanie faktycznie pobrało, łącznie z pakietami pobranymi przez skrypty instalacyjne i przywróconymi z cache. SBOM każdego wcześniejszego buildu jest zachowywany, więc na pytanie „czy jakikolwiek build zainstalował axios 1.14.1 w oknie ataku?” odpowiada historia buildów, wraz z okresem, w którym Państwa to dotyczyło, tak daleko wstecz, jak sięga okres przechowywania.

Znane złośliwe wydania, które mają opublikowane CVE, takie jak backdoor w xz, są oznaczane jak każda inna podatność, a bramka polityki może blokować buildy, które je zawierają. CRACI nie wykrywa nowego złośliwego pakietu na podstawie zachowania ani reputacji.

Polityka egress w CRACI blokuje połączenia z hostami, których build nie potrzebuje, co ogranicza to, co złośliwy skrypt instalacyjny może wysłać na zewnątrz, nawet w ataku, którego nikt wcześniej nie widział. Gdy klient poprosi o dowody, mogą Państwo wyeksportować SBOM dla używanych przez niego wersji w formacie CycloneDX lub SPDX i go przesłać. CRACI obsługuje VEX.

Proszę odpowiedzieć na pytanie „czy to nas dotyczyło?” na podstawie historii buildów lub przeczytać więcej o tym, jak działają ataki na łańcuch dostaw.

Kiedy CRACI nie jest rozwiązaniem

  • Potrzebują Państwo pomocy w samej komunikacji. Doradztwo PR i prawne to inna praca.
  • Dotknięte oprogramowanie nie było budowane w CRACI. CRACI rejestruje buildy GitHub Actions uruchamiane na jego runnerach; inne systemy CI są na roadmapie.
  • Pytanie dotyczy produktu dostawcy, którego nie budowali Państwo sami. SBOM-y dostawców można dodać do CRACI, ale odpowiedź jest tylko tak dobra jak SBOM dostawcy.
  • Muszą Państwo wychwycić zupełnie nowy złośliwy pakiet, zanim pojawi się jakikolwiek biuletyn. CRACI oznacza znane złośliwe wydania po opublikowaniu biuletynu z CVE; nie wykrywa malware na podstawie zachowania ani reputacji (reagowanie na podatności zero-day).

Najczęściej zadawane pytania

Co powiedzieć klientom, gdy o ataku na łańcuch dostaw mówią media?

W ciągu kilku godzin wysłać pierwsze oświadczenie: że wiedzą Państwo o ataku, że sprawdzają Państwo swoje produkty i buildy, co wiadomo do tej pory i kiedy nastąpi aktualizacja. Następnie, gdy tylko da się ją poprzeć zapisami buildów, wysłać potwierdzoną odpowiedź dla wskazanych wersji produktów, a dalsze informacje, gdy cokolwiek się zmieni.

Co powinno zawierać pierwsze oświadczenie?

Jedno zdanie o tym, co się stało, informację, że sprawdzają Państwo swoje produkty i systemy buildów, co udało się dotąd ustalić, termin kolejnej aktualizacji i kontakt. Nie może mówić „nie dotyczy” przed sprawdzeniem, spekulować o atakującym ani nikogo obwiniać.

Jak powiedzieć „nie dotyczy nas”, nie obiecując za wiele?

Wymienić sprawdzone produkty i wersje, zakres dat sprawdzonych buildów i wykorzystane dowody, na przykład zapis komponentów zainstalowanych przez każdy build wydania. Mówić „nie dotyczy” dla tych wersji, zaproponować SBOM lub oświadczenie VEX i obiecać aktualizację, jeśli cokolwiek się zmieni. Unikać sformułowań „w 100% bezpieczne” i „w pełni bezpieczne”.

Co powinien zawierać komunikat dla klientów „dotyczy nas”?

Których produktów i wersji to dotyczy, od kiedy i do której wersji z poprawką, ryzyko opisane prostym językiem, co klient powinien teraz zrobić (zaktualizować, wymienić poświadczenia, zablokować hosty), co Państwo już zrobili, kiedy nastąpi kolejna aktualizacja i z kim się kontaktować.

Jakie dowody powinny stać za stwierdzeniem „nie dotyczy”?

Dla każdej wersji używanej przez klientów zapis tego, co zainstalował build, który ją wytworzył, a nie dzisiejszy lockfile. Do tego zapisy każdego buildu uruchomionego w oknie ataku, a w przypadku ataków kradnących poświadczenia informacja, czy w zadaniach, które mogły uruchomić złośliwy kod, były obecne sekrety.

Czy atak na łańcuch dostaw trzeba zgłosić na podstawie Cyber Resilience Act?

Być może. Od 11 września 2026 roku producenci produktów z elementami cyfrowymi sprzedawanych w UE muszą zgłaszać aktywnie wykorzystywane podatności i poważne incydenty mające wpływ na bezpieczeństwo produktu: wczesne ostrzeżenie w ciągu 24 godzin, zgłoszenie w ciągu 72 godzin i raport końcowy. To, czy dany atak się kwalifikuje, muszą ocenić Państwo wraz z prawnikami.

Jak szybko odpowiedzieć klientom?

W ciągu kilku godzin, pierwszym oświadczeniem, nawet jeśli mówi ono tylko, że trwa sprawdzanie i kiedy nastąpi aktualizacja. Potwierdzona odpowiedź przychodzi, gdy tylko da się ją udowodnić. Szybkie, uczciwe „sprawdzamy” robi dla zaufania więcej niż spóźnione „nie dotyczy”.