Vydání 1.107.0 populární LLM proxy bylo na PyPI necelé dvě hodiny a neslo zloděje přihlašovacích údajů. Útočník se dostal k tokenům tří vývojářů, přepsal release pipeline a nechal si artefakty podepsat z repozitáře, který se od pravého lišil jediným spojovníkem. Vývojáři LiteLLM potvrdili, že vydání 1.107.0 z 21. října obsahovalo malware, který z napadených strojů odesílal cloudové přihlašovací údaje, API klíče k jazykovým modelům a privátní klíče SSH. Na PyPI byl balíček dostupný od 11:39:51 do 13:23 UTC, kontejnerové image na Docker Hubu až do 14:20 UTC. Posledním prokazatelně nezasaženým vydáním je 1.106.2. LiteLLM je proxy, která sjednocuje API různých poskytovatelů modelů pod jedno rozhraní, takže týmy přes ni posílají provoz na OpenAI, Anthropic, Bedrock i vlastní endpointy. Socket odhaduje zhruba 23 milionů stažení týdně. Právě proto je tahle krádež nepříjemná dvakrát: kdo LiteLLM provozuje jako centrální gateway, má v jejím okolí naskládané klíče ke všem poskytovatelům zároveň. A je to druhý úspěšný útok na dodavatelský řetězec tohoto projektu za letošní rok.
Pipeline padla za hodinu a půl
Oficiální zápis incidentu drží minutovou osu. V 10:08:29 UTC zablokovala branch protection neoprávněnou změnu v privátním release workflow, a pět sekund po tom ji privilegovaný vývojářský token přepsal a změnu protlačil silou. V 10:46:39 upravený workflow nastartoval staging běh, jenže ne nad pravým repozitářem BerriAI/litellm: zdrojem byl Berri-AI/litellm, napodobenina odlišená jediným spojovníkem. Produkční pipeline se rozjela v 11:08:53 a schvalovací bránu jí v 11:11:18 odkývl druhý vývojářský token. Mezi 11:39:51 a 11:40:13 doputovalo na PyPI sedm wheelů, dva pro macOS, čtyři pro Linux, jeden pro Windows. V 11:46:56 se publikovaly kontejnery. A v 11:53:49 třetí token smazal záznamy o produkčním i staging běhu, takže vyšetřovatelům zmizela část logů. Oficiální tag 1.107.0 na GitHubu je přitom čistý. Kdo si ho prošel, nenašel nic, protože provenience podepsaných artefaktů ukazovala na útočníkův repozitář, ne na kód v tagu. Shrnutí na začátku zápisu navíc uvádí jako čas kompromitace 4:00 PST, tedy 12:00 UTC. To si s vlastní osou událostí odporuje.
Spouštělo se to při každém startu Pythonu
Instalace podstrčila do knihovního adresáře tři soubory: cook.pth, cook.py a sitecustomize.py. Trik je v tom prvním. Soubory s příponou .pth Python vykoná při startu interpretu a cook.pth neobsahuje nic než import cook. Sběrač se tedy rozběhl i v prostředí, kde nikdo LiteLLM nikdy neimportoval.
Stačilo spustit python. Nebo pip.
Ten sběrač má podle analýzy Socketu šestnáct modulů. Bral přihlašovací údaje k AWS, Azure, Google Cloudu, Kubernetu, Dockeru, Vaultu a Terraformu, konfigurace CI, obsah souborů .env a .netrc, privátní klíče SSH, GPG a TLS, databáze Chromia a Firefoxu včetně cookies, historii shellu, proměnné prostředí i metadata instancí. Zvlášť vybíral soubory s přihlášením k nástrojům Codex, Claude, Gemini a Cursor. A pokud našel nastavenou DATABASE_URL, dotázal se přímo tabulek LiteLLM_CredentialsTable a LiteLLM_ProxyModelTable, kde si proxy drží klíče poskytovatelů. Výsledek zašifroval AES-256-CBC, klíč zabalil RSA-4096 a odeslal jako gzip archiv přes HTTP POST na adresu /healthcheck na doméně litellm.dev. Socket v IOC uvádí variantu s www, oficiální zápis adresu bez něj.
Druhý soubor, sitecustomize.py, běžel jako démon na pozadí. Každou hodinu se podíval do souboru v jednom repozitáři na GitHubu, a kdyby tam našel doménu, stáhl si z ní a spustil další Python kód. Bez kontroly podpisu nebo hashe. Socket v 13:01 hlásil, že ukazatel vrací prázdnou odpověď, The Hacker News o den později už chybu 404, takže tahle část útoku zhasla brzy. Sběrač v cook.pth na tom nebyl závislý.
Tokeny ležely v logu
Jak se útočník dostal ke třem sadám vývojářských přihlašovacích údajů, projekt zatím neví jistě. Ředitel bezpečnosti Oliver Jensen uvedl, že šlo o OAuth tokeny z GitHub CLI patřící účtům tří inženýrů. Na jednom interním nasazení LiteLLM, které bylo vystavené do internetu, tým našel neznámý účet s nenápadným jménem a domnívá se, že tokeny útočník vytáhl z logů té instance. Vstup sám zůstává nepotvrzený, podezření padá na nedávno opravenou zranitelnost, jejíž zveřejnění má embargo do 27. října. A teď detail pro každého, kdo si loguje těla HTTP odpovědí: podle zápisu incidentu umí Claude Code vložit uživatelův OAuth token z GitHub CLI do těla odpovědi. Kdo ukládá odpovědi do logu, uloží si s nimi i token. Nejdřív mi na celém případu přišel nejhorší ten napodobený repozitář. Po přečtení osy ale vidím slabší místo jinde: tým v pondělí dočasně rozšířil oprávnění k vydávání, aby dva inženýři mohli vypustit backporty opravy. V době útoku to rozšíření pořád platilo.
Co dělat, když jste 1.107.0 nainstalovali
Projekt i analytici se shodují na jednom: odinstalovat nestačí. Pokud na stroji s přístupem do internetu kdokoli spustil Python, berte exfiltraci jako hotovou.
- Nespouštějte v zasaženém prostředí jeho vlastní python ani pip. Oba znovu vykonají cook.pth.
- Hledejte litellm-1.107.0.dist-info, cook.pth, cook.py a sitecustomize.py. Markery /tmp/.pconce* a /tmp/remote_code_loader.lock ukazují, že exfiltrace proběhla nebo že démon běží, jejich absence ale nic nedokazuje.
- Ukončete odpojený proces držící /tmp/remote_code_loader.lock, smažte ty soubory i odpovídající .pyc v pycache a prostředí radši postavte znovu.
- Připněte 1.106.2, nejlépe přes digest. Starší vydání projekt jako prokazatelně čistá neoznačil.
- Rotujte z čistého stroje všechno, kam ten host dosáhl: IAM roli instance, klíče poskytovatelů v databázi proxy, master a virtuální klíče, heslo v DATABASE_URL.
- V CloudTrailu se podívejte na volání GetCallerIdentity z role instance kolem času instalace a na použití jejích údajů odjinud než z vaší infrastruktury.
Že útočník nic neodkládal, dokumentuje Wiz. Asi čtyři a půl hodiny po odeslání dat začal ověřovat ukradené přístupové údaje k AWS z napadených CI runnerů a uzlů Kubernetu a zkoušel přístup k modelům v Amazon Bedrocku. V několika prostředích si vylistoval IAM role, uživatele, access keys i údaje o účtu a logování.
Druhý zásah za rok
Březnový útok na LiteLLM skončil archivem o velikosti 153 GB. Hudson Rock ho v srpnu rozebral a napojil na 2 488 firemních domén, mezi nimi AWS, Samsung, Cisco a Salesforce. CloudSEK tehdy mluvil o bezmála 2 500 organizacích a 434 000 CI/CD pipelinách. Jak velký bude dopad toho říjnového, zatím nikdo neodhadl. LiteLLM po incidentu přesouvá vydávání do privátního repozitáře, přechází na Trusted GitHub Publishers, zamkne tagy kontejnerových image a začne je podepisovat. Zákazníky privátního enterprise registru podle projektu útok nezasáhl. Vyšetřování pokračuje a tým upozorňuje, že u zasažených účtů na GitHubu zatím nedokáže vyloučit další přístup. Pro české týmy z toho plyne nepohodlná věc. Centrální LLM gateway je dobrý návrh, jenže taky jediný bod, kde se sejdou klíče od všech poskytovatelů. Kdo přes LiteLLM točí provoz a nemá připnuté digesty, měl tenhle týden smůlu dvakrát, jednou u verze a jednou u floating tagů latest a main-stable.
Zdroje
- Contained: Oct 21, 2026 LiteLLM release v1.107.0 Compromised – oficiální zápis incidentu, LiteLLM
- LiteLLM PyPI Package and Docker Images Compromised to Steal Cloud and AI Credentials – Socket, technická analýza a IOC
- LiteLLM hit by second supply chain attack this year, users urged to rotate credentials – Help Net Security
- LiteLLM Compromised in Supply Chain Attack Delivering Credential Stealer and Backdoor – The Hacker News
- LiteLLM supply chain attack hoovers up passwords and secrets – The Register