Malicious litellm 1.107.0 shipped a credential stealer and RAT through PyPI and Docker
Malicious litellm 1.107.0 on PyPI and Docker ran a credential stealer and RAT at Python startup. Last safe pre-incident release is 1.106.2.
- Published
- Updated
- Ecosystem
- PyPIAI developer toolsOpen source
- Fixed in
- Clean releases v1.106.3 and v1.106.4 resumed 24 October 2026 (StepSecurity); 1.106.2 was the last safe release before the incident (Datadog, Wiz). BerriAI will skip 1.107.0 permanently.
- Exploitation
- Yes. The payload ran at every Python interpreter start and exfiltrated credentials; Wiz observed the attacker checking stolen AWS instance-role credentials with sts:GetCallerIdentity and bedrock:ListFoundationModels, consistent with LLMjacking.
What happened
- 21 October 2026, 11:39 UTC: malicious
litellm==1.107.0was published to PyPI; PyPI quarantined it around 13:20 to 13:23 UTC, and affected Docker images were removed or repointed by about 13:53 to 14:20 UTC. The package was available for roughly two hours (Datadog; StepSecurity). Wiz counted about 49,000 downloads in that window (Wiz). - The compromised release carried both an infostealer and a remote access trojan (RAT). Datadog described it as adding files that run “even if LiteLLM is never imported” (Datadog; Aikido).
- Root cause (per BerriAI’s postmortem, reported by sources). A configuration file containing a master key for an internal LiteLLM tool was committed to a public GitHub repository on 27 May 2026; the commit was removed about three hours later but the key was never revoked and stayed valid for over four months (The Register; GitGuardian).
- 10 October 2026: the attacker used that key to obtain the GitHub CLI OAuth token of a LiteLLM GitHub organization owner, a token not scoped to specific repositories, then stole tokens from two more maintainers (The Register; GitGuardian).
- 21 October 2026: the attacker built the release from a lookalike repository,
Berri-AI/litellm(one hyphen offBerriAI/litellm), and used a second maintainer’s token to satisfy the production approval step. The application source was byte-identical to the legitimate code; the payload was injected via the build, using apyproject.tomlmaturin directivedata = "cook"that bundled acook/directory into the wheels (Datadog; Aikido; Microsoft). - GitGuardian notes this follows an earlier, separate LiteLLM compromise; Hudson Rock’s analysis of that earlier exposure describes a 153GB archive of 433,909 files attributed to 2,488 organizations, figures that relate to the earlier incident, not to 1.107.0 (GitGuardian).
Affected versions
- PyPI:
litellm==1.107.0, all seven platform wheels (macOS x86_64/arm64, manylinux aarch64/x86_64, musllinux aarch64/x86_64, win_amd64) carry the payload. The source distribution has a tamperedpyproject.tomlbut no payload files (Datadog; StepSecurity). - Docker / GHCR:
v1.107.0onghcr.io/berriai/litellm,ghcr.io/berriai/litellm-database,ghcr.io/berriai/litellm-non_rootanddocker.io/litellm/litellm. The floating tagslatest,main-latestandmain-stablepointed to the malicious image on 21 October from about 11:46 to 14:20 UTC (Datadog; Aikido). - Not affected (per StepSecurity):
1.107.0rc1,1.107.0rc2, and the1.106.x,1.105.x,1.104.xand1.103.xlines; the1.107.0.dev1,dev3pre-releases were not inspected (StepSecurity). - Safe / fixed: Datadog and Wiz name
1.106.2as the last safe release (Datadog; Wiz). StepSecurity says clean releases resumed on 24 October asv1.106.3andv1.106.4, recommends pinning1.106.4or the backports1.105.5,1.104.7or1.103.9, and notes 1.107.0 will be skipped permanently (StepSecurity).
How the malware works
- Startup hooks. The wheel drops
cook.pth,cook.pyandsitecustomize.pyinto site-packages, outside thelitellm/package.cook.pthcontainsimport cook, which Python runs at every interpreter start;cook.pydeobfuscates and runs the stealer in a daemon thread;sitecustomize.pyis imported automatically by Python and carries both a collector and the remote loader. The payload fires on any Python or pip launch, LiteLLM import or not (Datadog; Microsoft). Microsoft calls the combined.pthplussitecustomize.pyapproach “the first documented case in the wild” (Microsoft). - Stealer (“privcollect”). Collects browser passwords and cookies (Chrome, Firefox, Edge, Safari); AWS, Azure and GCP credentials including instance metadata (IMDS); AI provider keys (OpenAI, Anthropic, Cohere and others) and AI coding tool configs (Claude, Codex, Gemini, Cursor, Copilot and others); SSH, GPG and TLS keys; Git, npm and PyPI tokens;
.envfiles and shell history; Docker, Kubernetes, Vault and CI/CD secrets; and, whenDATABASE_URLis set, upstream provider keys from the LiteLLM proxy’sLiteLLM_CredentialsTableandLiteLLM_ProxyModelTable. On Linux it also reads other processes’ environments via procfs (Datadog; Wiz; Endor Labs). - Exfiltration. Harvested data is encrypted with AES-256-CBC, the AES key wrapped with a 4,096-bit RSA key (OAEP), then sent by HTTP POST to
www.litellm[.]dev/healthcheckwith a hardcodedX-Tokenheader (Datadog; Microsoft). - RAT / remote code loader. A daemon (guarded by
/tmp/remote_code_loader.lock) reads a hostname hourly from a GitHub dead-drop file, then downloads and executes Python from/codepyon that host with no signature check. The dead drop held only test/empty values when observed and the GitHub repo was removed, so no second stage was confirmed; the loader does not run on Windows, but the stealer does (Datadog; Aikido; StepSecurity). - Post-exploitation. Wiz observed the attacker, about 4.5 hours after exfiltration (16:20 to 17:01 UTC), checking stolen AWS instance-role credentials from CI runners and Kubernetes nodes with
sts:GetCallerIdentity, thenbedrock:ListFoundationModels, consistent with LLMjacking; some environments also saw IAM enumeration (Wiz).
Indicators of compromise
Files / host. cook.pth, cook.py, sitecustomize.py in site-packages; /tmp/.pc_once_72129118c59f5636c0bb (stealer upload marker); /tmp/remote_code_loader.lock (loader running); .pc_e_* / .pc_sq_* temp staging; environment variable PRIVCOLLECT_ACTIVE=1; build config data = "cook" under [tool.maturin] (Datadog; Endor Labs; StepSecurity).
Network. www.litellm[.]dev/healthcheck (exfiltration); header X-Token: XWiA8gZNa7NcX2XRoAEb; raw.githubusercontent[.]com/letters9813/pythonclient-test/main/domain.txt (C2 dead drop, since removed); any /codepy request (Datadog; Microsoft).
Attacker artifacts. Lookalike repo github[.]com/Berri-AI/litellm; GitHub account letters9813; commit-author email ckdi82fkoos@proton.me; malicious head commit 20535d8fa11f786a6c24df7488a0e449ed5f09ad; attacker IPs 168.100.8.57, 165.227.201.8 (Wiz), plus 69.48.229.143 and 199.91.221.39 (StepSecurity) (Wiz; StepSecurity).
Hashes (SHA-256), Linux/macOS variants. cook.pth 7f191632e7320705d154b85204f1ae546b543acbd7e8861229b76f5042b92bdb; cook.py 9dd0a3926f96a37eb86cf1ee2310d9be93139cc4ebef3ef9e2efe9531390be25; sitecustomize.py 34bef04fe88ac9d0aae0475630b1738681d15b94f233ac8aa46eacf5968305fa. Windows variants: cook.pth 84dc8c82c0a4a4a62552ef826b49fcc86d1a5c4a5d0f2c06665723f93d129d7d; cook.py 03ac2a8b752605d1d7710979c17ff18b03dd978203ba23ba97fd8ce3d6f897ea; sitecustomize.py b6122440d0d9cb1eb1ade9933f49214da8c31288de7710c076c2680dfa528465 (Microsoft; Endor Labs). Container image index digest: sha256:1bbcb1443bc962e45f5aad53fe3d2c30600e0379715fb6c664cdd3ac126c339e (Datadog).
What to do
- Scope exposure. Search lockfiles, requirements and CI logs for
1.107.0; check environments forcook.pthand thedist-info; check local and Kubernetes images by digest, not mutable tags (Datadog). - Do not run Python or pip in a suspect environment, each launch re-triggers the payload. Inspect with trusted tools from a clean system (Microsoft).
- Contain and rebuild. Kill any process holding
/tmp/remote_code_loader.lock, removecook.pth,cook.py,sitecustomize.pyand their__pycache__, and rebuild from clean artifacts; removing thelitellmpackage alone is not sufficient (StepSecurity; Microsoft). - Rotate all reachable credentials from a clean machine, cloud keys, AI provider and AI-tool tokens, SSH/GPG/TLS keys, Git/npm/PyPI tokens, Kubernetes/Vault/registry secrets, and on proxy hosts the stored provider keys, master key, salt key and
DATABASE_URLpassword. Revoke active sessions, since rotation may not invalidate every token (Datadog; StepSecurity). - Hunt in logs. Look for POSTs to
www.litellm.dev/healthcheck, requests to the GitHub dead-drop path or any/codepy, and in CloudTrail forGetCallerIdentityand Bedrock calls from instance roles or from the listed IPs (Microsoft; StepSecurity). - Pin to a safe version,
1.106.2, or clean1.106.3/1.106.4, pin container images by digest, and block1.107.0in your package proxy. Fromv1.106.3, images are signed with a new key (StepSecurity).
Sources
- Datadog Security Labs: LiteLLM supply chain compromise, what you need to know (21 October 2026)
- Aikido: LiteLLM compromised again, infostealer and RAT found in version 1.107.0 (21 October 2026)
- Wiz: LiteLLM Compromised, Steals Credentials (21 October 2026)
- Endor Labs: LiteLLM 1.107.0 Compromised, Python Startup Hooks Steal Cloud, AI, and Proxy Credentials (22 October 2026)
- Microsoft Security: Inside the LiteLLM 1.107.0 supply chain compromise, credential theft through Python startup hooks (23 October 2026)
- StepSecurity: litellm 1.107.0 Compromised on PyPI and Docker, Credential Stealer and Hourly Remote Code Loader (26 October 2026)
- The Register: LiteLLM supply chain attack started with an exposed master key (26 October 2026)
- GitGuardian: Inside the LiteLLM hack, 153GB, 433,909 Files, 2,488 Organizations (4 November 2026)