Wygenerowana abstrakcyjna ilustracja na tle w bladym szaroniebieskim odcieniu: wysoki, ciemny panel w kolorze łupkowym stoi na lewo od środka, cienka bladocyjanowa wiązka biegnie poziomo przez niego i rozchodzi się po prawej stronie w szeroki stożek światła na polu małych geometrycznych bloków. Większość bloków leży w chłodnym cieniu; jeden klaster w pobliżu środka wiązki świeci ciepłym bursztynem. W tle znajduje się delikatna siatka projektu i cienkie koncentryczne łuki. Nie pojawiają się żadne teksty, liczby, osoby, znaki firmowe ani logo organizacji. Logo OrcaRouter jest nałożone w prawym dolnym rogu.
AI Safety Incidents

Clinejection: Jak tytuł zgłoszenia dotarł do tokena npm Cline'a

Autor

Rowan Sterling

Data publikacji

Najnowsze modele · 20Zobacz wszystkie modele →
Benchmarki: Artificial Analysis · aktualizowane codziennie
Powrót do wszystkich wpisów

9 lutego 2026 r. badacz bezpieczeństwa Adnan Khan opublikował relację o luce, którą prywatnie zgłosił firmie Cline 1 stycznia: asystent kodowania AI o otwartym kodzie źródłowym podłączył automatyczny triażer zgłoszeń, zbudowany na GitHub Action claude-code-action firmy Anthropic, do promptu, który wklejał dowolny tytuł przychodzącego zgłoszenia GitHub bezpośrednio do instrukcji modelu. Każde konto GitHub mogło go uruchomić, otwierając zgłoszenie, a w reprodukcji Khana tytuł sformułowany jako instrukcja skłonił agenta do uruchomienia polecenia powłoki w ramach workflow. Następnie prześledził drogę od tego punktu zaczepienia, przez zatruwanie pamięci podręcznej GitHub Actions, do poświadczeń wydania dla VS Code Marketplace, OpenVSX i npm. Osiem dni po tym, jak Cline naprawił workflow, token publikacji npm, który Cline uważał za zmieniony, został użyty do opublikowania cline 2.3.0, co zainstalowało OpenClaw na każdej maszynie, na której zainstalowano pakiet. Pełny wpis, wraz z jego ocenami ważności i pewności, znajduje się w Orca AI Incident Archive, obok sąsiednich zapisów dotyczących łańcucha dostaw z tego samego okresu.

Dwie daty, nie jedna

Archiwum datuje ten rekord na 9 lutego 2026 r., z dokładnością do dnia, i jest to dzień, w którym Khan opublikował swoją relację na adnanthekhan.com. Nie jest to dzień, w którym pojawił się złośliwy pakiet. Sama podatność została wprowadzona 21 grudnia 2025 r. w commicie, który dodał workflow triage do repozytorium cline/cline, i pozostawała aktywna, dopóki Cline nie usunął tego workflow 9 lutego. Nieautoryzowana publikacja w npm nastąpiła 17 lutego, osiem dni po poprawce i czterdzieści siedem dni po pierwszym prywatnym zgłoszeniu Khana.

Trzymanie tych dwóch dat osobno ma znaczenie, ponieważ najistotniejszy fakt w sprawie znajduje się w luce między nimi: drzwi zamknięto 9 lutego, ale klucz, który intruz zdążył skopiować, nadal działał 17 lutego. Sprostowanie samego Cline'a, wysłane do Khana 17 lutego i przytoczone w jego wpisie, ujmuje to wprost: „Kiedy 9 lutego rotowaliśmy poświadczenia, token publikacji npm nie został prawidłowo unieważniony. Usunięto niewłaściwy token, a ujawniony pozostał aktywny”.

Łańcuch: od tytułu zgłoszenia do tokenu wydania

Podatnym plikiem był .github/workflows/claude-issue-triage.yml, który uruchamiał się przy zdarzeniu issues i wywoływał anthropics/claude-code-action@v1 z Claude Opus 4.5, przypiętym w workflow jako claude-opus-4-5-20251101. Khan cytuje konfigurację workflow: allowed_non_write_users ustawiono na wildcard "*", więc każde konto GitHub mogło uruchomić agenta po prostu otwierając issue, a claude_args przekazywało --allowedTools z Bash, Read, Write, Edit, Glob, Grep, WebFetch i WebSearch. To Bash miał znaczenie. Dawał modelowi możliwość wykonywania poleceń powłoki wewnątrz workflow uruchamianego w kontekście gałęzi domyślnej.

Prompt interpolował tytuł zgłoszenia bez jego oczyszczenia. Khan w swoim proof of concept użył tytułu zaczynającego się od „Błąd narzędzia.” i kontynuował instrukcją zainstalowania pakietu pomocniczego z konkretnego commita, po czym przechodził do triage'u. Odwołanie do commita wskazywało na fork, którego package.json zawierał skrypt preinstall, który uruchamiał polecenie curl do punktu końcowego kontrolowanego przez atakującego, zanim npm zdążył cokolwiek zainstalować. Ponieważ instalacja przebiegała przez narzędzie Bash, model nigdy nie sprawdził, co zostało uruchomione. Khan odtworzył to na kopii lustrzanej repozytorium Cline i raportuje, że agent wykonał ładunek w każdej próbie.

Wykonanie kodu w workflow triage nie stanowi samo w sobie dostępu do poświadczeń wydania. Ten krok wynikał z właściwości GitHub Actions, którą Khan udokumentował w wydanym w 2024 r. narzędziu o nazwie Cacheract: każdy workflow może odczytywać i zapisywać pamięć podręczną repozytorium, mając pełną kontrolę nad kluczami i wersjami pamięci podręcznej, nawet workflow, który nigdy nie deklaruje kroku buforowania. Zadanie triage działało na gałęzi domyślnej, więc dzieliło zakres pamięci podręcznej z nocnymi zadaniami publikowania, które faktycznie przywracały node_modules z pamięci podręcznej i faktycznie miały tokeny publikowania.

Wpisy pamięci podręcznej są niezmienne, więc atakujący nie może po prostu nadpisać wpisu, który przywróci zadanie wydania. Sposobem Khana na obejście tego było wykorzystanie zmiany polityki GitHuba z 20 listopada 2025 r., która sprawiła, że usługa natychmiast usuwała wpisy pamięci podręcznej, gdy pamięć podręczna repozytorium przekroczyła 10 GB, w kolejności najdawniej używanych. Zalej pamięć podręczną powyżej 10 GB, a legalne wpisy się zestarzeją; przejmij zwolnione klucze zatrutą zawartością, a następne zadanie, które je przywróci, będzie uruchamiać kod atakującego. Cacheract automatyzuje całą sekwencję w ramach jednego uruchomienia workflow i utrzymuje się, nadpisując action.yml akcji actions/checkout, tak aby krok końcowy akcji uruchamiał ładunek na końcu każdego zadania.

Ostatnim ogniwem w łańcuchu jest zadanie nocne, które uruchamia się około 2:00 UTC, przywraca zatrute node_modules i detonuje. Na zewnątrz wychodzą VSCE_PAT, OVSX_PAT i NPM_RELEASE_TOKEN — poświadczenia odpowiednio dla VS Code Marketplace, OpenVSX i npm. Czy każde ogniwo zadziałało na własnym repozytorium Cline'a w tej kolejności, to osobne pytanie, którym zajmujemy się poniżej.

A self-built HTML card titled 'Six steps from an issue title to a release token', badged 'Clinejection · GHSA-9ppg-jx86-fqw7', subtitled 'The chain as Adnan Khan describes it, with the workflow configuration he quotes'. Six numbered rows read: 1, Issue opened on cline/cline, the title carries the instructions and allowed_non_write_users is set to the wildcard; 2, claude-issue-triage.yml runs, claude-code-action with Bash, Read, Write, Edit, Glob, Grep, WebFetch and WebSearch; 3, npm install from a fork commit, the fork's package.json carries a preinstall script and the model runs it through Bash; 4, Cache flooded past 10 GB, GitHub's LRU eviction removes the legitimate entries and frees their keys; 5, Poisoned entries claim the keys, the nightly jobs restore attacker content as node_modules; 6, Nightly job runs at about 2 AM UTC, VSCE_PAT, OVSX_PAT and NPM_RELEASE_TOKEN leave the runner. A footer reads 'Source: Adnan Khan, Clinejection, 9 February 2026; Cline advisory GHSA-9ppg-jx86-fqw7.' The OrcaRouter logo is composited in the bottom-right corner.

Dlaczego nocne poświadczenia były poświadczeniami produkcyjnymi

Oczywisty zarzut jest taki, że wydania nocne i produkcyjne powinny mieć różne sekrety. Odpowiedź Khana jest taka, że rozdzielenie było nominalne. OpenVSX i VS Code Marketplace wiążą token publikacji z tożsamością wydawcy, a nie z pojedynczym rozszerzeniem, a zarówno stabilne, jak i nocne rozszerzenia Cline zostały opublikowane pod tą samą tożsamością, którą Khan identyfikuje w OpenVSX jako saoudrizwan. W npm model tokenów o drobnoziarnistych uprawnieniach jest powiązany z pakietem, a Cline publikował swoje stabilne i nocne kompilacje CLI w tym samym pakiecie cline. Token wydany dla zadania nocnego mógł zatem opublikować artefakt produkcyjny, co jest dokładnie tym, co wydarzyło się osiem dni później.

Sposób, w jaki Khan sam ujmuje ten wpływ, opiera się na skali: cytuje ogłoszenie Cline o przekroczeniu 5 milionów instalacji i zauważa, że aktualizacja rozszerzenia wypchnięta przy użyciu skradzionych poświadczeń wykonuje się w kontekście każdego programisty, którego edytor aktualizuje się automatycznie, z uprawnieniami tego programisty oraz wszelkimi kluczami, tokenami i kodem źródłowym znajdującymi się na maszynie.

Co faktycznie opublikowano i jaki to miało skutek

Opublikowanym artefaktem był cline 2.3.0 i był niewielki. Własne znaczniki czasu rejestru npm wskazują, że 2.3.0 opublikowano 17 lutego 2026 o 11:26:51 UTC, a czysty 2.4.0 tego samego dnia o 19:23:08 UTC — ekspozycję, którą biuletyn doradczy Cline szacuje na około osiem godzin, do momentu oznaczenia 2.3.0 jako przestarzałego o 11:30 czasu PT. Plik package.json pakietu zawierał jedną dodaną linię — skrypt postinstall o treści npm install -g openclaw@latest. Biuletyn doradczy Cline, GHSA-9ppg-jx86-fqw7, stwierdza, że nie zmieniono żadnych innych plików pakietu oraz że dist/cli.mjs jest bajtowo identyczny z legalną kompilacją 2.2.3.

OpenClaw to prawdziwy framework agentów AI o otwartym kodzie źródłowym, a nie złośliwe oprogramowanie, i komunikat Cline'a mówi to wprost: to prawowity projekt, ale jego instalacja nie była autoryzowana ani zamierzona. Endor Labs, które przeanalizowało tarball, oceniło ogólny wpływ jako niski, ponieważ instalacja nie uruchomiła demona Gateway OpenClaw. Analiza StepSecurity ocenia drugą stronę: globalna instalacja pozostawia framework na dysku wraz z dowolnymi poświadczeniami i dostępem do plików, jakie ma instalujący użytkownik, a konstrukcja OpenClaw — trwała lokalna brama z API operatorskim — czyni go czymś o wysokiej wartości do znalezienia tam. Te dwie oceny nie są sprzeczne. Jedna opisuje, co działało w tym oknie czasowym; druga opisuje, co pozostawiono po tym.

Liczba pobrań to jedyna wartość, którą trzeba traktować ostrożnie. StepSecurity podało, że skompromitowana wersja została pobrana około 4000 razy, zanim została wycofana, a The Register powtórzył tę liczbę. Endor Labs określiło miesięczną liczbę pobrań cline w okresie od 19 stycznia do 17 lutego na 418 545, co opisuje normalny ruch pakietu, a nie złośliwą kompilację. Żadna z tych liczb nie dotyczy maszyn: liczba pobrań to nie liczba dotkniętych deweloperów, a żadna ze stron nie opublikowała liczby instalacji dla wersji 2.3.0. Zespół Microsoft Threat Intelligence poinformował na X, że 17 lutego zaobserwował „niewielki, ale zauważalny wzrost” instalacji OpenClaw wynikający ze skryptu instalacyjnego Cline, jak podało The Hacker News.

Zapis doradczy GitHuba dla GHSA-9ppg-jx86-fqw7 nie zawiera ani CVE, ani CWE, a jego waga to niska. Ta ocena dotyczy nieszkodliwego ładunku, a nie kradzieży danych uwierzytelniających, i dziwnie kontrastuje z krytyczną oceną samego incydentu w archiwum. W doradztwie wskazano 2.3.0 jako wersję podatną, a 2.4.0 jako poprawkę.

Ujawnienie, na które Cline nie odpowiedział

Oś czasu działań Khana przed publikacją to ta część zapisu, która najmniej dotyczy modelu, a najbardziej procesu. 1 stycznia 2026 r. przesłał GHSA przez prywatny system zgłaszania podatności GitHuba i tego samego dnia wysłał e-mail do kontaktu ds. bezpieczeństwa wymienionego na stronie zaufania Cline. 8 stycznia wysłał ponowną wiadomość do dewelopera Cline. 18 stycznia próbował wysłać wiadomość prywatną do CEO Cline na X. 7 lutego napisał ponownie i nie otrzymał nic poza automatycznie wygenerowanym numerem zgłoszenia. Opublikował 9 lutego.

Cline scalił poprawkę, pull request 9211, około trzydziestu minut do godziny później. PR usuwa trzy pliki workflow — claude-issue-triage.yml, claude-pr-review.yml i cline-pr-review.yml — oraz usuwa buforowanie z publish.yml, publish-nightly.yml, npm-nightly.yaml i npm-main.yaml, w sumie siedem plików, a kroki instalacji są teraz bezwarunkowe, skoro nie ma już trafienia w pamięć podręczną, na którym można polegać.

Publiczna odpowiedź Cline'a z 10 lutego, cytowana w poście Khana, przyjmowała ustalenie i wymieniała natychmiastowe środki zaradcze: usunięcie przepływów pracy przeglądu botów dla zgłoszeń i PR, usunięcie actions/cache z przepływów pracy publikowania obsługujących dane uwierzytelniające wydania oraz rotację odpowiednich danych uwierzytelniających, w tym tokenów bota, dostawcy i publikowania. Przyznano także sposób postępowania: „przyznajemy, że nasz czas reakcji na Twoje początkowe zgłoszenie był nieakceptowalny. Zgłoszenie złożone 1 stycznia nie powinno wymagać publicznego ujawnienia 9 lutego, aby zostało rozpatrzone”.

11 lutego Cline poinformował, że zakończył pełną rotację VSCE_PAT, OVSX_PAT i NPM_RELEASE_TOKEN oraz że audyt każdego wydania we wszystkich trzech kanałach dystrybucji między 21 grudnia 2025 a 9 lutego 2026 wykazał, że każda wersja w Marketplace i OpenVSX odpowiadała wydaniu GitHub oznaczonemu tagiem, a wszystkie 41 wersji npm były zgodne ze źródłem. Stwierdził, że „w domniemanym oknie ekspozycji” nie opublikowano żadnego nieautoryzowanego wydania. Sześć dni później sprostował to w cytowanej powyżej wiadomości: token npm nie został unieważniony, a 2.3.0 opublikowano za jego pomocą.

A self-built HTML card titled 'From private report to public disclosure', subtitled 'Khan's pre-publication timeline, and what followed'. Eight dated rows read: 21 Dec 2025, vulnerable claude-issue-triage.yml committed; 1 January 2026, GHSA filed and email sent to Cline's listed security contact; 8 January 2026, follow-up email to a Cline developer, no reply; 18 January 2026, direct message to Cline's CEO on X, no reply; 7 February 2026, final email, automated ticket number only; 9 February 2026, public disclosure and PR 9211 merged within about an hour; 11 February 2026, Cline reports full rotation and a clean audit; 17 February 2026, cline 2.3.0 published with a still-valid npm token. A footer reads 'Times and dates as recorded by Adnan Khan; the 17 February publish timestamp is corroborated by the npm registry.' The OrcaRouter logo is composited in the bottom-right corner.

Ustalony, przypisany, nierozwiązany

• Potwierdzone. Konfiguracja workflow jest publiczna i została opublikowana przed poprawką. Khan odtworzył atak typu prompt injection na kopii lustrzanej repozytorium. Cline scalił poprawkę i wydał biuletyn bezpieczeństwa, który potwierdza publikację wersji 2.3.0, dodanie wiersza postinstall, niezmieniony plik binarny CLI, ośmiogodzinne okno oraz awarię tokenu. Znaczniki czasu rejestru npm dla wersji 2.3.0 i 2.4.0 są zgodne z czasami podanymi w biuletynie. Archiwum ocenia wpis jako krytyczny, przy pewności A, z odnotowaną rzeczywistą szkodą i bez flagi sporu.

• Przypisane, lecz nieustalone. Kto opublikował 2.3.0, pozostaje otwartą kwestią przypisania. Opublikowana przez Michaela Bargury’ego i automatyczne narzędzie śledcze o nazwie Raptor analiza kryminalistyczna z 19 lutego wskazuje konto GitHub o nazwie glthub-actions i z wysoką pewnością podaje, że konto to utworzyło fork cline/cline, otworzyło zgłoszenie 8904 w dniu 28 stycznia 2026 o 03:51 UTC ze wstrzykniętym tytułem oraz użyło commita z forka do uruchomienia payloadu z gista. Khan potwierdził, że konta gcbrun i Dev11940518 należą do niego, a glthub-actions nie. W momencie publikacji analizy konto było już usunięte lub zawieszone, a Cline nie wskazał nikogo. Tożsamość należy traktować jako ustalenie strony trzeciej.

• Spór dotyczy charakteru, nie faktów. Bargury ocenia epizod jako spójny z demonstracją badawczą w zakresie bezpieczeństwa, a nie ze złośliwą kampanią, wskazując na niegroźny payload i historię aktora wobec repozytorium automatyzacji New Relic. Cline nazywa to nieautoryzowaną publikacją, a Khan pisze, że aktor, który opublikował 2.3.0, jest „przypuszczalnie” tym samym, który zatruł cache. Nikt nie wykazał zamiaru wyrządzenia szkody i nikt nie wykazał, że go nie było.

• Nierozstrzygnięte. Nota przedpublikacyjna samego Khana ostrożnie podchodzi do kwestii, którą późniejsze doniesienia czasami spłaszczają: między 31 stycznia a 3 lutego 2026 r. kilka nocnych przebiegów zakończyło się niepowodzeniem na kroku Post Checkout, który nie wygenerował żadnego wyjścia, co jest wskaźnikiem kompromitacji według Cacheract; workflow triage jest najbardziej oczywistą ścieżką, ale nie udowodniono, że był punktem wejścia tej aktywności. Żadna ze stron nie opublikowała również dowodów, że użyto tokenów Marketplace lub OpenVSX; jedynym artefaktem, jaki ktokolwiek przedstawił, jest build npm.

A self-built HTML card titled 'What the record supports', subtitled 'One column is documented, one is other people's findings, one is simply open', split into three columns. The first, headed Established, lists four items: the triage workflow interpolated issue titles into the prompt and allowed any GitHub account to trigger it, with Bash among the tools; Khan reproduced the injection on a mirror of the repository; Cline's advisory GHSA-9ppg-jx86-fqw7 confirms cline 2.3.0, the added postinstall line, the unchanged CLI binary and an eight-hour window; npm registry timestamps place 2.3.0 at 11:26 UTC and 2.4.0 at 19:23 UTC on 17 February 2026. The second, headed Attributed, lists three items: the account glthub-actions and issue 8904 come from a third-party forensic write-up, not from Cline; that the actor copied Khan's public proof-of-concept repository is an inference from timing and from his own statement; that the publish was a research demonstration rather than an attack is one analyst's assessment. The third, headed Unresolved, lists three items: whether the triage workflow was the entry point for the late-January cache anomalies; whether any Marketplace or OpenVSX credential was used, with no artefact published; how many distinct machines installed 2.3.0, since about 4,000 is a download count. A footer reads 'Sources: Adnan Khan, Clinejection, 9 February 2026; Cline, GHSA-9ppg-jx86-fqw7; StepSecurity, 17 February 2026; Endor Labs, 18 February 2026; Michael Bargury and Raptor, 19 February 2026.' The OrcaRouter logo is composited in the bottom-right corner.

Co się potem zmieniło?

Remediacja objęła kilka warstw jednocześnie i warto nazwać każdą z nich, ponieważ odpowiadają one na różne aspekty tego niepowodzenia. Workflow, do którego mógł dotrzeć ktoś z zewnątrz, został usunięty, a nie zawężony. Buforowanie usunięto z czterech workflowów wydawniczych przechowujących sekrety publikacji, a nie z całego repozytorium — i to właśnie ta zmiana przerywa pivot. Poświadczenia zostały wymienione, a po korekcie z 17 lutego unieważniono właściwy token npm. W biuletynie Cline stwierdzono, że publikowanie w npm korzysta teraz z proweniencji OIDC przez GitHub Actions, a analiza metadanych StepSecurity pokazuje, dlaczego miało to znaczenie: legalne wydania już zawierały poświadczenia proweniencji, a 2.3.0 było odstępstwem opublikowanym przez konto człowieka. Luka polegała na tym, że ścieżka długotrwałego tokena pozostała otwarta obok zaufanego publikowania, co jest konkretnie tym, co Endor Labs przekonuje, że opiekunowie powinni zamknąć. Cline opublikował GHSA-9ppg-jx86-fqw7, oznaczył 2.3.0 jako przestarzałe z komunikatem, że nie należy go instalować, i skierował użytkowników do 2.4.0 lub nowszej.

Rekomendacje strukturalne {{1}}Khana{{/1}} idą dalej niż to, co zostało wdrożone, i warto zapisać je jako {{2}}jego{{/2}}, a nie jako {{3}}Cline'a{{/3}}: usuń {{4}}Bash{{/4}}, {{5}}Write{{/5}} i {{6}}Edit{{/6}} z dowolnego przepływu pracy triage i pozostaw mu odczyty plików oraz konkretne wywołania {{7}}GitHub CLI{{/7}}, których potrzebuje; nigdy nie przywracaj pamięci podręcznej w zadaniu, które przechowuje sekrety publikacji produkcyjnych; i nadaj wydaniom nocnym własną przestrzeń nazw rejestru oraz dedykowaną tożsamość publikowania nieprodukcyjnego, tak aby skradziony token wydania nocnego nie mógł w ogóle opublikować stabilnego wydania.

Ośmiodniowa luka między poprawką a złośliwą publikacją to szczegół, który sprawia, że ten zapis warto zachować. Każdy krok w łańcuchu był znaną techniką; Khan opublikował narzędzie do zatruwania pamięci podręcznej, a badanie PromptPwnd firmy Aikido Security z grudnia 2025 r. udokumentowało ten sam wzorzec błędnej konfiguracji triage'u. W incydent w łańcuchu dostaw złożyły się: przepływ pracy, który pozwalał tekstowi obcej osoby dotrzeć do powłoki, pamięć podręczna współdzielona z zadaniami mającymi klucze wydania oraz rotacja tokenów, która pominęła jedno poświadczenie. Każda z trzech poprawek samodzielnie przerwałaby łańcuch; trzecia przyszła osiem dni za późno.